Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

logs on demand #455

Merged
merged 23 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/main/java/org/gridsuite/study/server/StudyConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ private StudyConstants() {

public static final String GROUP_UUID = "groupUuid";
public static final String REPORT_UUID = "reportUuid";
public static final String REPORTER_ID = "reporterId";
public static final String UUIDS = "uuids";
public static final String QUERY_PARAM_ERROR_ON_GROUP_NOT_FOUND = "errorOnGroupNotFound";
public static final String QUERY_PARAM_ERROR_ON_REPORT_NOT_FOUND = "errorOnReportNotFound";
public static final String QUERY_PARAM_REPORT_DEFAULT_NAME = "defaultName";
public static final String QUERY_PARAM_REPORT_SEVERITY_LEVEL = "severityLevels";
public static final String QUERY_PARAM_REPORT_WITH_ELEMENTS = "withElements";
public static final String QUERY_PARAM_REPORT_TASKKEY_FILTER = "taskKeyFilter";
public static final String QUERY_PARAM_RECEIVER = "receiver";
public static final String HEADER_RECEIVER = "receiver";
public static final String HEADER_BUS_ID = "busId";
Expand Down
31 changes: 28 additions & 3 deletions src/main/java/org/gridsuite/study/server/StudyController.java
Original file line number Diff line number Diff line change
Expand Up @@ -1006,12 +1006,37 @@ public ResponseEntity<Void> stopSecurityAnalysis(@Parameter(description = "Study
return ResponseEntity.ok().build();
}

@GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get node report with its parent nodes")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The node report"), @ApiResponse(responseCode = "404", description = "The study/node is not found")})
public ResponseEntity<List<ReporterModel>> getParentNodesReport(@Parameter(description = "Study uuid") @PathVariable("studyUuid") UUID studyUuid,
@Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid,
@Parameter(description = "Node only report") @RequestParam(value = "nodeOnlyReport", required = false, defaultValue = "true") boolean nodeOnlyReport,
@Parameter(description = "Severity levels") @RequestParam(name = "severityLevels", required = false) Set<String> severityLevels) {
studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid);
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getParentNodesReport(nodeUuid, nodeOnlyReport, severityLevels));
}

@GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/report", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get node report")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The node report"), @ApiResponse(responseCode = "404", description = "The study/node is not found")})
public ResponseEntity<List<ReporterModel>> getNodeReport(@Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid,
@Parameter(description = "Node only report") @RequestParam(value = "nodeOnlyReport", required = false, defaultValue = "true") boolean nodeOnlyReport) {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getNodeReport(nodeUuid, nodeOnlyReport));
public ResponseEntity<List<ReporterModel>> getNodeReport(@Parameter(description = "Study uuid") @PathVariable("studyUuid") UUID studyUuid,
@Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid,
@Parameter(description = "The report Id") @RequestParam(name = "reportId", required = false) String reportId,
@Parameter(description = "Severity levels") @RequestParam(name = "severityLevels", required = false) Set<String> severityLevels) {
studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid);
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getNodeReport(nodeUuid, reportId, severityLevels));
}

@GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/subreport", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get node sub-report")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The node subreport"), @ApiResponse(responseCode = "404", description = "The study/node is not found")})
public ResponseEntity<ReporterModel> getSubReport(@Parameter(description = "Study uuid") @PathVariable("studyUuid") UUID studyUuid,
@Parameter(description = "Node uuid") @PathVariable("nodeUuid") UUID nodeUuid,
@Parameter(description = "The report Id") @RequestParam(name = "reportId") String reportId,
@Parameter(description = "Severity levels") @RequestParam(name = "severityLevels", required = false) Set<String> severityLevels) {
studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid);
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(studyService.getSubReport(reportId, severityLevels));
}

@DeleteMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/report")
Expand Down
38 changes: 28 additions & 10 deletions src/main/java/org/gridsuite/study/server/service/ReportService.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import static org.gridsuite.study.server.StudyConstants.*;
Expand Down Expand Up @@ -56,22 +57,39 @@ public void setReportServerBaseUri(String reportServerBaseUri) {
this.reportServerBaseUri = reportServerBaseUri;
}

private String getReportServerURI() {
private String getReportsServerURI() {
return this.reportServerBaseUri + DELIMITER + REPORT_API_VERSION + DELIMITER + "reports" + DELIMITER;
}

public ReporterModel getReport(@NonNull UUID reportUuid, @NonNull String defaultName) {
var path = UriComponentsBuilder.fromPath("{reportUuid}")
.queryParam(QUERY_PARAM_REPORT_DEFAULT_NAME, defaultName)
.queryParam(QUERY_PARAM_ERROR_ON_REPORT_NOT_FOUND, false)
.buildAndExpand(reportUuid)
.toUriString();
private String getSubReportsServerURI() {
return this.reportServerBaseUri + DELIMITER + REPORT_API_VERSION + DELIMITER + "subreports" + DELIMITER;
}

public ReporterModel getReport(@NonNull UUID id, @NonNull String defaultName, String taskKeyFilter, Set<String> severityLevels) {
var uriBuilder = UriComponentsBuilder.fromPath("{id}")
.queryParam(QUERY_PARAM_REPORT_DEFAULT_NAME, defaultName)
.queryParam(QUERY_PARAM_REPORT_WITH_ELEMENTS, true)
.queryParam(QUERY_PARAM_REPORT_SEVERITY_LEVEL, severityLevels);
if (taskKeyFilter != null && !taskKeyFilter.isEmpty()) {
uriBuilder.queryParam(QUERY_PARAM_REPORT_TASKKEY_FILTER, taskKeyFilter);
}
return reportServerCall(id, this.getReportsServerURI(), uriBuilder);
}

public ReporterModel getSubReport(@NonNull UUID id, Set<String> severityLevels) {
var uriBuilder = UriComponentsBuilder.fromPath("{id}")
.queryParam(QUERY_PARAM_REPORT_SEVERITY_LEVEL, severityLevels);
return reportServerCall(id, this.getSubReportsServerURI(), uriBuilder);
}

private ReporterModel reportServerCall(UUID id, String serverUri, UriComponentsBuilder uriBuilder) {
var path = uriBuilder.buildAndExpand(id).toUriString();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
List<ReporterModel> reporters = restTemplate.exchange(this.getReportServerURI() + path, HttpMethod.GET, new HttpEntity<>(headers), new ParameterizedTypeReference<List<ReporterModel>>() {
List<ReporterModel> reporters = restTemplate.exchange(serverUri + path, HttpMethod.GET, new HttpEntity<>(headers), new ParameterizedTypeReference<List<ReporterModel>>() {
}).getBody();
// TODO : Remove this hack when fix to avoid key collision in hades2 will be done
ReporterModel reporter = new ReporterModel(reportUuid.toString(), reportUuid.toString());
ReporterModel reporter = new ReporterModel(id.toString(), id.toString());
if (reporters != null) {
reporters.forEach(reporter::addSubReporter);
}
Expand All @@ -83,7 +101,7 @@ public void deleteReport(@NonNull UUID reportUuid) {
.queryParam(QUERY_PARAM_ERROR_ON_REPORT_NOT_FOUND, false)
.buildAndExpand(reportUuid)
.toUriString();
restTemplate.delete(this.getReportServerURI() + path);
restTemplate.delete(this.getReportsServerURI() + path);
}

public void deleteTreeReports(@NonNull Map<UUID, String> treeReportsKeys) {
Expand Down
36 changes: 27 additions & 9 deletions src/main/java/org/gridsuite/study/server/service/StudyService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.powsybl.commons.reporter.ReporterModel;
import com.powsybl.commons.reporter.TypedValue;
import com.powsybl.iidm.network.*;
import com.powsybl.security.LimitViolation;
import com.powsybl.iidm.network.VariantManagerConstants;
Expand Down Expand Up @@ -38,6 +39,7 @@
import org.gridsuite.study.server.networkmodificationtree.dto.*;
import org.gridsuite.study.server.dto.dynamicsimulation.event.EventInfos;
import org.gridsuite.study.server.networkmodificationtree.entities.NodeEntity;
import org.gridsuite.study.server.networkmodificationtree.entities.NodeType;
import org.gridsuite.study.server.notification.NotificationService;
import org.gridsuite.study.server.notification.dto.NetworkImpactsInfos;
import org.gridsuite.study.server.repository.*;
Expand Down Expand Up @@ -1747,12 +1749,23 @@ private void checkStudyContainsNode(UUID studyUuid, UUID nodeUuid) {
}

@Transactional(readOnly = true)
public List<ReporterModel> getNodeReport(UUID nodeUuid, boolean nodeOnlyReport) {
return getSubReportersByNodeFrom(nodeUuid, nodeOnlyReport);
public ReporterModel getSubReport(String subReportId, Set<String> severityLevels) {
return reportService.getSubReport(UUID.fromString(subReportId), severityLevels);
}

private List<ReporterModel> getSubReportersByNodeFrom(UUID nodeUuid, boolean nodeOnlyReport) {
List<ReporterModel> subReporters = getSubReportersByNodeFrom(nodeUuid);
@Transactional(readOnly = true)
public List<ReporterModel> getNodeReport(UUID nodeUuid, String reportId, Set<String> severityLevels) {
// Hack: filtering Root node with its nodeId in report db does not work
// TODO : Remove this hack when the taskKey of the root node will be replaced by the node uuid
AbstractNode nodeInfos = networkModificationTreeService.getNode(nodeUuid);
String taskKeyFilter = nodeInfos.getType() == NodeType.ROOT ? null : nodeUuid.toString();
return getSubReporters(nodeUuid, UUID.fromString(reportId), severityLevels, taskKeyFilter);
}

@Transactional(readOnly = true)
public List<ReporterModel> getParentNodesReport(UUID nodeUuid, boolean nodeOnlyReport, Set<String> severityLevels) {
AbstractNode nodeInfos = networkModificationTreeService.getNode(nodeUuid);
List<ReporterModel> subReporters = getSubReporters(nodeUuid, nodeInfos.getReportUuid(), severityLevels, null);
if (subReporters.isEmpty()) {
return subReporters;
} else if (nodeOnlyReport) {
Expand All @@ -1762,20 +1775,25 @@ private List<ReporterModel> getSubReportersByNodeFrom(UUID nodeUuid, boolean nod
return subReporters;
}
Optional<UUID> parentUuid = networkModificationTreeService.getParentNodeUuid(UUID.fromString(subReporters.get(0).getTaskKey()));
return parentUuid.isEmpty() ? subReporters : Stream.concat(getSubReportersByNodeFrom(parentUuid.get(), false).stream(), subReporters.stream()).collect(Collectors.toList());
if (parentUuid.isEmpty()) {
return subReporters;
}
List<ReporterModel> parentReporters = self.getParentNodesReport(parentUuid.get(), false, severityLevels);
return Stream.concat(parentReporters.stream(), subReporters.stream()).collect(Collectors.toList());
}
}

private List<ReporterModel> getSubReportersByNodeFrom(UUID nodeUuid) {
AbstractNode nodeInfos = networkModificationTreeService.getNode(nodeUuid);
ReporterModel reporter = reportService.getReport(nodeInfos.getReportUuid(), nodeInfos.getId().toString());
private List<ReporterModel> getSubReporters(UUID nodeUuid, UUID reportUuid, Set<String> severityLevels, String taskKeyfilter) {
ReporterModel reporter = reportService.getReport(reportUuid, nodeUuid.toString(), taskKeyfilter, severityLevels);
Map<String, List<ReporterModel>> subReportersByNode = new LinkedHashMap<>();
reporter.getSubReporters().forEach(subReporter -> subReportersByNode.putIfAbsent(getNodeIdFromReportKey(subReporter), new ArrayList<>()));
reporter.getSubReporters().forEach(subReporter ->
subReportersByNode.get(getNodeIdFromReportKey(subReporter)).addAll(subReporter.getSubReporters())
);
return subReportersByNode.keySet().stream().map(nodeId -> {
ReporterModel newSubReporter = new ReporterModel(nodeId, nodeId);
// For a node report, pass the reportId to the Front as taskValues, to allow direct access
Map<String, TypedValue> taskValues = Map.of("id", new TypedValue(reportUuid.toString(), "ID"));
ReporterModel newSubReporter = new ReporterModel(nodeId, nodeId, taskValues);
subReportersByNode.get(nodeId).forEach(newSubReporter::addSubReporter);
return newSubReporter;
}).collect(Collectors.toList());
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/org/gridsuite/study/server/StudyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ public void setup() throws IOException {
networkModificationService.setNetworkModificationServerBaseUri(baseUrlWireMock);

// FIXME: remove lines when dicos will be used on the front side
// Override the custom module to restore the standard module in order to have the original serialization used like the report server
mapper.registerModule(new ReporterModelJsonModule() {
@Override
public Object getTypeId() {
Expand Down Expand Up @@ -902,7 +903,7 @@ public void testLogsReport() throws Exception {
UUID studyUuid = createStudy("userId", CASE_UUID);
UUID rootNodeUuid = getRootNodeUuid(studyUuid);

MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/report", studyUuid, rootNodeUuid).header(USER_ID_HEADER, "userId"))
MvcResult mvcResult = mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/parent-nodes-report", studyUuid, rootNodeUuid).header(USER_ID_HEADER, "userId"))
.andExpect(status().isOk()).andReturn();
String resultAsString = mvcResult.getResponse().getContentAsString();
List<ReporterModel> reporterModel = mapper.readValue(resultAsString, new TypeReference<List<ReporterModel>>() { });
Expand Down
Loading
Loading