Skip to content

Commit ee8c93f

Browse files
authored
Merge pull request #2606 from akto-api-security/threat_query_optimizations
optimise threat cateogry count api
2 parents cfba671 + c7c6c67 commit ee8c93f

File tree

2 files changed

+50
-23
lines changed

2 files changed

+50
-23
lines changed

apps/dashboard/src/main/resources/struts.xml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8387,7 +8387,9 @@
83878387
<param
83888388
name="includeProperties">^actionErrors.*</param>
83898389
</result>
8390-
<result name="SUCCESS" type="json"> </result>
8390+
<result name="SUCCESS" type="json">
8391+
<param name="includeProperties">^categoryCounts.*</param>
8392+
</result>
83918393
<result name="ERROR" type="json">
83928394
<param name="statusCode">422</param>
83938395
<param name="ignoreHierarchy">false</param>
@@ -8419,7 +8421,9 @@
84198421
<param
84208422
name="includeProperties">^actionErrors.*</param>
84218423
</result>
8422-
<result name="SUCCESS" type="json"> </result>
8424+
<result name="SUCCESS" type="json">
8425+
<param name="includeProperties">^categoryCounts.*</param>
8426+
</result>
84238427
<result name="ERROR" type="json">
84248428
<param name="statusCode">422</param>
84258429
<param name="ignoreHierarchy">false</param>
@@ -8451,7 +8455,9 @@
84518455
<param
84528456
name="includeProperties">^actionErrors.*</param>
84538457
</result>
8454-
<result name="SUCCESS" type="json"> </result>
8458+
<result name="SUCCESS" type="json">
8459+
<param name="includeProperties">^actorsCounts.*</param>
8460+
</result>
84558461
<result name="ERROR" type="json">
84568462
<param name="statusCode">422</param>
84578463
<param name="ignoreHierarchy">false</param>
@@ -8483,7 +8489,9 @@
84838489
<param
84848490
name="includeProperties">^actionErrors.*</param>
84858491
</result>
8486-
<result name="SUCCESS" type="json"> </result>
8492+
<result name="SUCCESS" type="json">
8493+
<param name="includeProperties">^threatActivityTimelines.*</param>
8494+
</result>
84878495
<result name="ERROR" type="json">
84888496
<param name="statusCode">422</param>
84898497
<param name="ignoreHierarchy">false</param>

apps/threat-detection-backend/src/main/java/com/akto/threat/backend/service/ThreatApiService.java

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.akto.threat.backend.service;
22

3+
import com.akto.dao.context.Context;
4+
import com.akto.log.LoggerMaker;
35
import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatApiRequest;
46
import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ListThreatApiResponse;
57
import com.akto.proto.generated.threat_detection.service.dashboard_service.v1.ThreatCategoryWiseCountRequest;
@@ -10,20 +12,26 @@
1012
import com.mongodb.client.MongoClient;
1113
import com.mongodb.client.MongoCollection;
1214
import com.mongodb.client.MongoCursor;
15+
1316
import java.util.ArrayList;
1417
import java.util.List;
1518
import java.util.Map;
19+
1620
import org.bson.Document;
1721

1822
public class ThreatApiService {
1923

2024
private final MongoClient mongoClient;
25+
private static final LoggerMaker loggerMaker = new LoggerMaker(ThreatApiService.class);
2126

2227
public ThreatApiService(MongoClient mongoClient) {
2328
this.mongoClient = mongoClient;
2429
}
2530

2631
public ListThreatApiResponse listThreatApis(String accountId, ListThreatApiRequest request) {
32+
33+
loggerMaker.info("listThreatApis start ts " + Context.now());
34+
2735
int skip = request.hasSkip() ? request.getSkip() : 0;
2836
int limit = request.getLimit();
2937
Map<String, Integer> sort = request.getSortMap();
@@ -106,44 +114,48 @@ public ListThreatApiResponse listThreatApis(String accountId, ListThreatApiReque
106114
e.printStackTrace();
107115
}
108116

117+
loggerMaker.info("listThreatApis end ts " + Context.now());
109118
return ListThreatApiResponse.newBuilder().addAllApis(apis).setTotal(total).build();
110119
}
111120

112121
public ThreatCategoryWiseCountResponse getSubCategoryWiseCount(
113-
String accountId, ThreatCategoryWiseCountRequest req) {
122+
String accountId, ThreatCategoryWiseCountRequest req) {
123+
124+
loggerMaker.info("getSubCategoryWiseCount start ts " + Context.now());
125+
114126
MongoCollection<Document> coll =
115127
this.mongoClient
116128
.getDatabase(accountId)
117129
.getCollection(MongoDBCollection.ThreatDetection.MALICIOUS_EVENTS, Document.class);
118130

119131
List<Document> pipeline = new ArrayList<>();
132+
133+
// 1. Match on time range
120134
if (req.getStartTs() != 0 || req.getEndTs() != 0) {
121-
Document matchFilter = new Document("$match",
122-
new Document("detectedAt", new Document("$gte", req.getStartTs()).append("$lte", req.getEndTs()))
123-
);
124-
pipeline.add(matchFilter);
135+
pipeline.add(new Document("$match",
136+
new Document("detectedAt",
137+
new Document("$gte", req.getStartTs())
138+
.append("$lte", req.getEndTs()))));
125139
}
126-
pipeline.add(
127-
new Document("$sort", new Document("category", 1).append("detectedAt", -1))); // sort
128-
pipeline.add(
129-
new Document(
130-
"$group",
131-
new Document(
132-
"_id",
133-
new Document("category", "$category").append("subCategory", "$subCategory"))
134-
.append("count", new Document("$sum", 1))));
135140

136-
pipeline.add(
137-
new Document(
138-
"$sort",
139-
new Document("category", -1).append("subCategory", -1).append("count", -1))); // sort
141+
// 3. Group by category and subCategory
142+
pipeline.add(new Document("$group",
143+
new Document("_id",
144+
new Document("category", "$category")
145+
.append("subCategory", "$subCategory"))
146+
.append("count", new Document("$sum", 1))));
147+
148+
// 4. Sort by count descending
149+
pipeline.add(new Document("$sort", new Document("count", -1)));
140150

141151
List<ThreatCategoryWiseCountResponse.SubCategoryCount> categoryWiseCounts = new ArrayList<>();
142152

143-
try (MongoCursor<Document> cursor = coll.aggregate(pipeline).cursor()) {
153+
// 5. Execute aggregation with controlled batch size
154+
try (MongoCursor<Document> cursor = coll.aggregate(pipeline).batchSize(1000).cursor()) {
144155
while (cursor.hasNext()) {
145156
Document doc = cursor.next();
146157
Document agg = (Document) doc.get("_id");
158+
147159
categoryWiseCounts.add(
148160
ThreatCategoryWiseCountResponse.SubCategoryCount.newBuilder()
149161
.setCategory(agg.getString("category"))
@@ -153,13 +165,18 @@ public ThreatCategoryWiseCountResponse getSubCategoryWiseCount(
153165
}
154166
}
155167

168+
loggerMaker.info("getSubCategoryWiseCount end ts " + Context.now());
169+
156170
return ThreatCategoryWiseCountResponse.newBuilder()
157171
.addAllCategoryWiseCounts(categoryWiseCounts)
158172
.build();
159173
}
160174

161175
public ThreatSeverityWiseCountResponse getSeverityWiseCount(
162176
String accountId, ThreatSeverityWiseCountRequest req) {
177+
178+
loggerMaker.info("getSeverityWiseCount start ts " + Context.now());
179+
163180
MongoCollection<Document> coll =
164181
this.mongoClient
165182
.getDatabase(accountId)
@@ -199,6 +216,8 @@ public ThreatSeverityWiseCountResponse getSeverityWiseCount(
199216
}
200217
}
201218

219+
loggerMaker.info("getSeverityWiseCount end ts " + Context.now());
220+
202221
return ThreatSeverityWiseCountResponse.newBuilder()
203222
.addAllCategoryWiseCounts(categoryWiseCounts)
204223
.build();

0 commit comments

Comments
 (0)