Skip to content

Commit 8e28b98

Browse files
hernaldourbinaoleg-odysseus
authored andcommitted
ATL-8: Atlas Usage Statistics
1 parent 53e27a6 commit 8e28b98

File tree

4 files changed

+102
-19
lines changed

4 files changed

+102
-19
lines changed

src/main/java/org/ohdsi/webapi/statistic/controller/StatisticController.java

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import com.opencsv.CSVWriter;
44

5-
import org.apache.commons.lang3.tuple.Pair;
5+
import org.ohdsi.webapi.shiro.TokenManager;
66
import org.ohdsi.webapi.statistic.dto.AccessTrendDto;
77
import org.ohdsi.webapi.statistic.dto.AccessTrendsDto;
88
import org.ohdsi.webapi.statistic.dto.EndpointDto;
@@ -11,9 +11,10 @@
1111
import org.ohdsi.webapi.statistic.service.StatisticService;
1212
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
1313
import org.springframework.stereotype.Controller;
14+
import org.springframework.web.context.request.RequestContextHolder;
15+
import org.springframework.web.context.request.ServletRequestAttributes;
1416

1517
import javax.ws.rs.Consumes;
16-
import javax.ws.rs.GET;
1718
import javax.ws.rs.POST;
1819
import javax.ws.rs.Path;
1920
import javax.ws.rs.Produces;
@@ -26,6 +27,8 @@
2627
import java.time.format.DateTimeFormatter;
2728
import java.util.ArrayList;
2829
import java.util.List;
30+
import java.util.Objects;
31+
import java.util.Optional;
2932
import java.util.stream.Collectors;
3033

3134
@Controller
@@ -34,6 +37,10 @@
3437
public class StatisticController {
3538
private StatisticService service;
3639

40+
public enum ResponseFormat {
41+
CSV, JSON
42+
}
43+
3744
private static final List<String[]> EXECUTION_STATISTICS_CSV_RESULT_HEADER = new ArrayList<String[]>() {{
3845
add(new String[]{"Date", "Source", "Execution Type"});
3946
}};
@@ -56,11 +63,16 @@ public StatisticController(StatisticService service) {
5663
@Consumes(MediaType.APPLICATION_JSON)
5764
public Response executionStatistics(ExecutionStatisticsRequest executionStatisticsRequest) {
5865
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
66+
String userID = executionStatisticsRequest.isShowUserInformation() ? extractUserID() : null;
5967

6068
SourceExecutionsDto sourceExecutions = service.getSourceExecutions(LocalDate.parse(executionStatisticsRequest.getStartDate(), formatter),
61-
LocalDate.parse(executionStatisticsRequest.getEndDate(), formatter), executionStatisticsRequest.getSourceKey());
69+
LocalDate.parse(executionStatisticsRequest.getEndDate(), formatter), executionStatisticsRequest.getSourceKey(), userID);
6270

63-
return prepareExecutionResultResponse(sourceExecutions.getExecutions(), "execution_statistics.zip");
71+
if (ResponseFormat.CSV.equals(executionStatisticsRequest.getResponseFormat())) {
72+
return prepareExecutionResultResponse(sourceExecutions.getExecutions(), "execution_statistics.zip");
73+
} else {
74+
return Response.ok(sourceExecutions).build();
75+
}
6476
}
6577

6678
/**
@@ -73,11 +85,16 @@ public Response executionStatistics(ExecutionStatisticsRequest executionStatisti
7385
@Consumes(MediaType.APPLICATION_JSON)
7486
public Response accessStatistics(AccessTrendsStatisticsRequest accessTrendsStatisticsRequest) {
7587
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
76-
88+
String userID = accessTrendsStatisticsRequest.isShowUserInformation() ? extractUserID() : null;
89+
7790
AccessTrendsDto trends = service.getAccessTrends(LocalDate.parse(accessTrendsStatisticsRequest.getStartDate(), formatter),
78-
LocalDate.parse(accessTrendsStatisticsRequest.getEndDate(), formatter), accessTrendsStatisticsRequest.getEndpoints());
91+
LocalDate.parse(accessTrendsStatisticsRequest.getEndDate(), formatter), accessTrendsStatisticsRequest.getEndpoints(), userID);
7992

80-
return prepareAccessTrendsResponse(trends.getTrends(), "execution_trends.zip");
93+
if (ResponseFormat.CSV.equals(accessTrendsStatisticsRequest.getResponseFormat())) {
94+
return prepareAccessTrendsResponse(trends.getTrends(), "execution_trends.zip");
95+
} else {
96+
return Response.ok(trends).build();
97+
}
8198
}
8299

83100
private Response prepareExecutionResultResponse(List<SourceExecutionDto> executions, String filename) {
@@ -121,12 +138,23 @@ private Response prepareResponse(List<String[]> data, String filename, List<Stri
121138
}
122139
}
123140

141+
private String extractUserID() {
142+
return Optional.ofNullable(RequestContextHolder.getRequestAttributes())
143+
.map(ServletRequestAttributes.class::cast)
144+
.map(ServletRequestAttributes::getRequest)
145+
.map(TokenManager::extractToken)
146+
.map(TokenManager::getSubject)
147+
.orElse(null);
148+
}
149+
124150
public static final class ExecutionStatisticsRequest {
125151
// Format - yyyy-MM-dd
126152
String startDate;
127153
// Format - yyyy-MM-dd
128154
String endDate;
129155
String sourceKey;
156+
ResponseFormat responseFormat;
157+
boolean showUserInformation;
130158

131159
public String getStartDate() {
132160
return startDate;
@@ -151,6 +179,22 @@ public String getSourceKey() {
151179
public void setSourceKey(String sourceKey) {
152180
this.sourceKey = sourceKey;
153181
}
182+
183+
public ResponseFormat getResponseFormat() {
184+
return responseFormat;
185+
}
186+
187+
public void setResponseFormat(ResponseFormat responseFormat) {
188+
this.responseFormat = responseFormat;
189+
}
190+
191+
public boolean isShowUserInformation() {
192+
return showUserInformation;
193+
}
194+
195+
public void setShowUserInformation(boolean showUserInformation) {
196+
this.showUserInformation = showUserInformation;
197+
}
154198
}
155199

156200
public static final class AccessTrendsStatisticsRequest {
@@ -161,6 +205,8 @@ public static final class AccessTrendsStatisticsRequest {
161205
// Key - method (POST, GET)
162206
// Value - endpoint ("{}" can be used as a placeholder, will be converted to ".*" in regular expression)
163207
List<EndpointDto> endpoints;
208+
ResponseFormat responseFormat;
209+
boolean showUserInformation;
164210

165211
public String getStartDate() {
166212
return startDate;
@@ -185,5 +231,21 @@ public List<EndpointDto> getEndpoints() {
185231
public void setEndpoints(List<EndpointDto> endpoints) {
186232
this.endpoints = endpoints;
187233
}
234+
235+
public ResponseFormat getResponseFormat() {
236+
return responseFormat;
237+
}
238+
239+
public void setResponseFormat(ResponseFormat responseFormat) {
240+
this.responseFormat = responseFormat;
241+
}
242+
243+
public boolean isShowUserInformation() {
244+
return showUserInformation;
245+
}
246+
247+
public void setShowUserInformation(boolean showUserInformation) {
248+
this.showUserInformation = showUserInformation;
249+
}
188250
}
189251
}

src/main/java/org/ohdsi/webapi/statistic/dto/AccessTrendDto.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
public class AccessTrendDto {
66
private String endpointName;
77
private LocalDate executionDate;
8+
private String userID;
89

9-
public AccessTrendDto(String endpointName, LocalDate executionDate) {
10+
public AccessTrendDto(String endpointName, LocalDate executionDate, String userID) {
1011
this.endpointName = endpointName;
1112
this.executionDate = executionDate;
13+
this.userID = userID;
1214
}
1315

1416
public String getEndpointName() {
@@ -26,4 +28,12 @@ public LocalDate getExecutionDate() {
2628
public void setExecutionDate(LocalDate executionDate) {
2729
this.executionDate = executionDate;
2830
}
31+
32+
public String getUserID() {
33+
return userID;
34+
}
35+
36+
public void setUserID(String userID) {
37+
this.userID = userID;
38+
}
2939
}

src/main/java/org/ohdsi/webapi/statistic/dto/SourceExecutionDto.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ public class SourceExecutionDto {
77
private String sourceName;
88
private String executionName;
99
private LocalDate executionDate;
10+
private String userID;
1011

11-
public SourceExecutionDto(String sourceName, String executionName, LocalDate executionDate) {
12+
public SourceExecutionDto(String sourceName, String executionName, LocalDate executionDate, String userID) {
1213
this.sourceName = sourceName;
1314
this.executionName = executionName;
1415
this.executionDate = executionDate;
16+
this.userID = userID;
1517
}
1618

1719
public String getSourceName() {
@@ -37,4 +39,12 @@ public LocalDate getExecutionDate() {
3739
public void setExecutionDate(LocalDate executionDate) {
3840
this.executionDate = executionDate;
3941
}
42+
43+
public String getUserID() {
44+
return userID;
45+
}
46+
47+
public void setUserID(String userID) {
48+
this.userID = userID;
49+
}
4050
}

src/main/java/org/ohdsi/webapi/statistic/service/StatisticService.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,26 +117,26 @@ public StatisticService() {
117117
logFileDateFormat = new SimpleDateFormat(dateString);
118118
}
119119

120-
public SourceExecutionsDto getSourceExecutions(LocalDate startDate, LocalDate endDate, String sourceKey) {
120+
public SourceExecutionsDto getSourceExecutions(LocalDate startDate, LocalDate endDate, String sourceKey, String userID) {
121121
Set<Path> paths = getLogPaths(startDate, endDate);
122122
List<SourceExecutionDto> executions = paths.stream()
123-
.flatMap(path -> extractSourceExecutions(path, sourceKey).stream())
123+
.flatMap(path -> extractSourceExecutions(path, sourceKey, userID).stream())
124124
.collect(Collectors.toList());
125125
return new SourceExecutionsDto(executions);
126126
}
127127

128-
public AccessTrendsDto getAccessTrends(LocalDate startDate, LocalDate endDate, List<EndpointDto> endpoints) {
128+
public AccessTrendsDto getAccessTrends(LocalDate startDate, LocalDate endDate, List<EndpointDto> endpoints, String userID) {
129129
Set<Path> paths = getLogPaths(startDate, endDate);
130130
List<AccessTrendDto> trends = paths.stream()
131-
.flatMap(path -> extractAccessTrends(path, endpoints).stream())
131+
.flatMap(path -> extractAccessTrends(path, endpoints, userID).stream())
132132
.collect(Collectors.toList());
133133
return new AccessTrendsDto(trends);
134134
}
135135

136-
private List<SourceExecutionDto> extractSourceExecutions(Path path, String sourceKey) {
136+
private List<SourceExecutionDto> extractSourceExecutions(Path path, String sourceKey, String userID) {
137137
try (Stream<String> stream = Files.lines(path)) {
138138
return stream
139-
.map(str -> getMatchedExecution(str, sourceKey))
139+
.map(str -> getMatchedExecution(str, sourceKey, userID))
140140
.filter(Optional::isPresent)
141141
.map(Optional::get)
142142
.collect(Collectors.toList());
@@ -146,13 +146,14 @@ private List<SourceExecutionDto> extractSourceExecutions(Path path, String sourc
146146
}
147147
}
148148

149-
private List<AccessTrendDto> extractAccessTrends(Path path, List<EndpointDto> endpoints) {
149+
private List<AccessTrendDto> extractAccessTrends(Path path, List<EndpointDto> endpoints, String userID) {
150150
List<Pattern> patterns = endpoints.stream()
151151
.map(endpointPair -> {
152152
String method = endpointPair.getMethod();
153153
String endpoint = endpointPair.getUrlPattern().replaceAll("\\{\\}", ".*");
154154
String regexpStr = ENDPOINT_REGEXP.replace("{METHOD_PLACEHOLDER}", method);
155155
regexpStr = regexpStr.replace("{ENDPOINT_PLACEHOLDER}", endpoint);
156+
regexpStr = regexpStr.replace("{USERID_PLACEHOLDER}", userID);
156157

157158
return Pattern.compile(regexpStr);
158159
})
@@ -163,7 +164,7 @@ private List<AccessTrendDto> extractAccessTrends(Path path, List<EndpointDto> en
163164
patterns.stream()
164165
.map(pattern -> pattern.matcher(str))
165166
.filter(matcher -> matcher.matches())
166-
.map(matcher -> new AccessTrendDto(matcher.group(2), LocalDate.parse(matcher.group(1))))
167+
.map(matcher -> new AccessTrendDto(matcher.group(2), LocalDate.parse(matcher.group(1)), matcher.group(3)))
167168
.findFirst()
168169
)
169170
.filter(Optional::isPresent)
@@ -175,12 +176,12 @@ private List<AccessTrendDto> extractAccessTrends(Path path, List<EndpointDto> en
175176
}
176177
}
177178

178-
private Optional<SourceExecutionDto> getMatchedExecution(String str, String sourceKey) {
179+
private Optional<SourceExecutionDto> getMatchedExecution(String str, String sourceKey, String userID) {
179180
return patternMap.entrySet().stream()
180181
.map(entry -> new ImmutablePair<>(entry.getKey(), entry.getValue().matcher(str)))
181182
.filter(pair -> pair.getValue().matches())
182183
.filter(pair -> sourceKey == null || (sourceKey != null && sourceKey.equals(pair.getValue().group(2))))
183-
.map(pair -> new SourceExecutionDto(pair.getValue().group(2), pair.getKey(), LocalDate.parse(pair.getValue().group(1))))
184+
.map(pair -> new SourceExecutionDto(pair.getValue().group(2), pair.getKey(), LocalDate.parse(pair.getValue().group(1)), userID))
184185
.findFirst();
185186
}
186187

0 commit comments

Comments
 (0)