Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • hbp-mip/portal-backend
1 result
Show changes
Commits on Source (5)
Showing
with 151 additions and 63 deletions
#######################################################
# Build the spring boot maven project
#######################################################
FROM maven:3.9.3-amazoncorretto-17 as mvn-build-env
FROM maven:3.9.3-amazoncorretto-17 AS mvn-build-env
MAINTAINER Thanasis Karampatsis <tkarabatsis@athenarc.gr>
ENV CODE_PATH="/opt/code"
......@@ -33,6 +33,11 @@ ENV APP_CONFIG_TEMPLATE="/opt/config/application.tmpl"
ENV APP_CONFIG_LOCATION="/opt/config/application.yml"
ENV SPRING_CONFIG_LOCATION="file:/opt/config/application.yml"
ENV SERVICE="portal-backend"
ENV FEDERATION="default"
ENV LOG_LEVEL="INFO"
ENV FRAMEWORK_LOG_LEVEL="INFO"
WORKDIR /opt
RUN apk add --no-cache curl
......@@ -40,7 +45,7 @@ RUN apk add --no-cache curl
#######################################################
# Install dockerize
#######################################################
ENV DOCKERIZE_VERSION v0.6.1
ENV DOCKERIZE_VERSION=v0.6.1
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz
......
......@@ -9,14 +9,6 @@ server:
forward-headers-strategy: native
### LOG LEVELS ###
logging:
level:
root: {{ default .Env.LOG_LEVEL_FRAMEWORK "ERROR" }}
eu:
hbp: {{ default .Env.LOG_LEVEL "INFO" }}
### DATABASE CONFIGURATION ###
spring:
datasource:
......
......@@ -44,6 +44,16 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
......
......@@ -7,16 +7,22 @@ import hbp.mip.utils.HTTPUtil;
import hbp.mip.utils.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static hbp.mip.utils.InputStreamConverter.convertInputStreamToString;
@Service
@EnableScheduling
public class AlgorithmService {
private static final Gson gson = new Gson();
......@@ -76,11 +82,29 @@ public class AlgorithmService {
return Collections.emptyList();
}
// Filter out algorithms with type "flower"
algorithms = algorithms.stream()
.filter(algorithm -> "exareme2".equals(algorithm.type()))
.collect(Collectors.toList());
logger.debug("Fetched " + algorithms.size() + " exareme2 algorithms.");
exareme2AlgorithmsSpecs.setAlgorithms(algorithms);
return algorithms;
}
@EnableAsync
public static class AlgorithmAggregator {
private final AlgorithmService algorithmService;
public AlgorithmAggregator(AlgorithmService algorithmService){
this.algorithmService = algorithmService;
}
@Async
@Scheduled(fixedDelayString = "${services.algorithmsUpdateInterval}000")
public void scheduleFixedRateTaskAsync() {
algorithmService.getExareme2Algorithms(new Logger("AlgorithmAggregator","(GET) /algorithms"));
}
}
/**
* Fetches the disabled algorithms from a .json file
*
......
......@@ -15,15 +15,33 @@ public record Exareme2AlgorithmRequestDTO(
String type
) {
public Exareme2AlgorithmRequestDTO(
public static Exareme2AlgorithmRequestDTO create(
UUID experimentUUID,
List<ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmParameterExecutionDTO> exaremeAlgorithmRequestParamDTOs,
List<ExperimentExecutionDTO.AlgorithmExecutionDTO.TransformerExecutionDTO> exaremeTransformers,
Exareme2AlgorithmSpecificationDTO exareme2AlgorithmSpecificationDTO) {
this(
// List of inputDataFields
List<String> inputDataFields = Arrays.asList("pathology", "dataset", "x", "y", "filter");
// Create lists to hold the separated DTOs
List<ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmParameterExecutionDTO> inputDataDTOs = new ArrayList<>();
List<ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmParameterExecutionDTO> parametersDTOs = new ArrayList<>();
// Split the DTOs into the respective lists
for (ExperimentExecutionDTO.AlgorithmExecutionDTO.AlgorithmParameterExecutionDTO dto : exaremeAlgorithmRequestParamDTOs) {
if (inputDataFields.contains(dto.name())) {
inputDataDTOs.add(dto);
} else {
parametersDTOs.add(dto);
}
}
// Call the constructor with the separated lists
return new Exareme2AlgorithmRequestDTO(
experimentUUID.toString(),
getInputData(exaremeAlgorithmRequestParamDTOs),
getParameters(exaremeAlgorithmRequestParamDTOs, exareme2AlgorithmSpecificationDTO),
getInputData(inputDataDTOs),
getParameters(parametersDTOs, exareme2AlgorithmSpecificationDTO),
getPreprocessing(exaremeTransformers, exareme2AlgorithmSpecificationDTO),
"exareme2"
);
......@@ -73,15 +91,13 @@ public record Exareme2AlgorithmRequestDTO(
return null;
}
// The input_data fields should be ignored and shouldn't be added in the parameters.
List<String> inputDataFields = Arrays.asList("pathology", "dataset", "x", "y", "filter");
HashMap<String, Object> exareme2Parameters = new HashMap<>();
exaremeAlgorithmRequestParamDTOs.forEach(parameter -> {
if (!inputDataFields.contains(parameter.name())){
Exareme2AlgorithmSpecificationDTO.Exareme2AlgorithmParameterSpecificationDTO paramSpecDto = exareme2AlgorithmSpecificationDTO.parameters().get(parameter.name());
exareme2Parameters.put(parameter.name(), convertStringToProperExareme2ParameterTypeAccordingToSpecs(parameter.value(), paramSpecDto));
Exareme2AlgorithmSpecificationDTO.Exareme2AlgorithmParameterSpecificationDTO paramSpecDto = exareme2AlgorithmSpecificationDTO.parameters().get(parameter.name());
if (paramSpecDto == null){
throw new InternalServerError("Parameter " + parameter.name() + " not found in algorithm:" + exareme2AlgorithmSpecificationDTO.name());
}
exareme2Parameters.put(parameter.name(), convertStringToProperExareme2ParameterTypeAccordingToSpecs(parameter.value(), paramSpecDto));
});
return exareme2Parameters;
}
......@@ -103,6 +119,9 @@ public record Exareme2AlgorithmRequestDTO(
if (transformerSpecificationDTO.isEmpty()) throw new InternalServerError("Missing the transformer: " + transformer_name);
Exareme2AlgorithmSpecificationDTO.Exareme2AlgorithmParameterSpecificationDTO paramSpecDto = transformerSpecificationDTO.get().parameters().get(param_name);
if (paramSpecDto == null){
throw new InternalServerError("Parameter " + parameter.name() + " not found in transformer:" + transformerSpecificationDTO.get().name());
}
transformerParameterDTOs.put(param_name, convertStringToProperExareme2ParameterTypeAccordingToSpecs(parameter.value(), paramSpecDto));
}
exareme2Preprocessing.put(transformer_name, transformerParameterDTOs);
......
......@@ -13,7 +13,8 @@ public record Exareme2AlgorithmSpecificationDTO(
String desc,
Exareme2AlgorithmInputdataSpecificationDTO inputdata,
Map<String, Exareme2AlgorithmParameterSpecificationDTO> parameters,
List<Exareme2TransformerSpecificationDTO> preprocessing
List<Exareme2TransformerSpecificationDTO> preprocessing,
String type
) {
@Override
public Map<String, Exareme2AlgorithmParameterSpecificationDTO> parameters() {
......
package hbp.mip.configurations;
import hbp.mip.utils.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class AuthenticationEventListener {
@EventListener
public void handleAuthenticationSuccess(AuthenticationSuccessEvent event) {
Authentication authentication = event.getAuthentication();
String username = authentication.getName();
Logger logger = new Logger(username, "LOGGING IN");
logger.info("User " + username + " has logged in successfully");
// If you need to log additional details:
authentication.getAuthorities().forEach(authority ->
logger.info("User " + username + " has authority " + authority.getAuthority())
);
}
}
......@@ -42,15 +42,15 @@ public class ExperimentAPI {
var logger = new Logger(activeUserService.getActiveUser(authentication).username(), "(GET) /experiments");
logger.info(
"Request for experiments with parameters: " +
"\n\tname -> " + name +
"\n\talgorithm -> " + algorithm +
"\n\tshared -> " + shared +
"\n\tviewed -> " + viewed +
"\n\tincludeShared -> " + includeShared +
"\n\torderBy -> " + orderBy +
"\n\tdescending -> " + descending +
"\n\tpage -> " + page +
"\n\tsize -> " + size
"name -> " + name +
" , algorithm -> " + algorithm +
" , shared -> " + shared +
" , viewed -> " + viewed +
" , includeShared -> " + includeShared +
" , orderBy -> " + orderBy +
" , descending -> " + descending +
" , page -> " + page +
" , size -> " + size
);
var experimentsDTO = experimentService.getExperiments(authentication,
name,
......@@ -71,7 +71,7 @@ public class ExperimentAPI {
@GetMapping(value = "/{uuid}")
public ResponseEntity<ExperimentDTO> getExperiment(Authentication authentication, @PathVariable("uuid") String uuid) {
var logger = new Logger(activeUserService.getActiveUser(authentication).username(), "(GET) /experiments/{uuid}");
var logger = new Logger(activeUserService.getActiveUser(authentication).username(), "(GET) /experiments/" + uuid);
logger.info("Request for experiment with id: " + uuid);
var experimentResponse = experimentService.getExperiment(authentication, uuid, logger);
logger.info("Experiment returned.");
......@@ -92,7 +92,7 @@ public class ExperimentAPI {
@PatchMapping(value = "/{uuid}")
public ResponseEntity<ExperimentDTO> updateExperiment(Authentication authentication, @RequestBody ExperimentDTO experimentRequest, @PathVariable("uuid") String uuid) {
var user = activeUserService.getActiveUser(authentication);
var logger = new Logger(user.username(), "(PATCH) /experiments/{uuid}");
var logger = new Logger(user.username(), "(PATCH) /experiments/" + uuid);
logger.info("Request for experiment update with id: " + uuid + ". Request Body: " + JsonConverters.convertObjectToJsonString(experimentRequest));
var experimentResponse = experimentService.updateExperiment(user, uuid, experimentRequest, logger);
logger.info("Experiment updated. Id: " + uuid);
......@@ -103,7 +103,7 @@ public class ExperimentAPI {
@RequestMapping(value = "/{uuid}", method = RequestMethod.DELETE)
public ResponseEntity<String> deleteExperiment(Authentication authentication, @PathVariable("uuid") String uuid) {
var user = activeUserService.getActiveUser(authentication);
var logger = new Logger(user.username(), "(DELETE) /experiments/{uuid}");
var logger = new Logger(user.username(), "(DELETE) /experiments/" + uuid);
logger.info("Request for experiment deletion with id: " + uuid);
experimentService.deleteExperiment(user, uuid, logger);
logger.info("Experiment deleted. Id: " + uuid);
......@@ -124,8 +124,8 @@ public class ExperimentAPI {
logger.info(
"Experiment (transient) finished. " +
"\n\tStatus: " + experimentResponse.status() +
"\n\tResult: " + experimentResponse.result()
" Status: " + experimentResponse.status() +
" Result: " + experimentResponse.result()
);
return new ResponseEntity<>(experimentResponse, HttpStatus.OK);
......
......@@ -172,7 +172,7 @@ public class ExperimentService {
experimentDAO.setStatus((exaremeExperimentAlgorithmResultDTO.code() >= 400)
? ExperimentDAO.Status.error : ExperimentDAO.Status.success);
} catch (Exception e) {
logger.error("Exareme2 algorithm execution failed: " + e.getMessage() + "\nStacktrace: " + Arrays.toString(e.getStackTrace()));
logger.error("Exareme2 algorithm execution failed: " + e.getMessage() + " Stacktrace: " + Arrays.toString(e.getStackTrace()));
experimentDAO.setStatus(ExperimentDAO.Status.error);
}
......@@ -289,36 +289,33 @@ public class ExperimentService {
if (algorithm.parameters() != null) {
algorithm.parameters().forEach(
params -> parametersLogMessage
.append(" ")
.append(" ")
.append(params.name())
.append(" -> ")
.append(params.value())
.append("\n"));
);
}
if (algorithm.preprocessing() != null) {
algorithm.preprocessing().forEach(transformer ->
{
parametersLogMessage
.append(" ")
.append(" ")
.append(transformer.name())
.append(" -> ")
.append("\n");
.append(" -> ");
if (transformer.parameters() != null) {
transformer.parameters().forEach(
transformerParams -> parametersLogMessage
.append(" ")
.append(" ")
.append(transformerParams.name())
.append(" -> ")
.append(transformerParams.value())
.append("\n"));
parametersLogMessage.append("\n");
.append(transformerParams.value()));
}
});
}
logger.debug("Algorithm " + algorithmName + " execution starting with parameters: \n" + parametersLogMessage);
logger.debug("Algorithm " + algorithmName + " execution starting with parameters: " + parametersLogMessage);
}
private String getExperimentDatasets(ExperimentExecutionDTO experimentExecutionDTO, Logger logger) {
......@@ -341,7 +338,7 @@ public class ExperimentService {
String algorithmName = experimentExecutionDTO.algorithm().name();
String algorithmEndpoint = exareme2AlgorithmsUrl + "/" + algorithmName;
Exareme2AlgorithmSpecificationDTO exareme2AlgorithmSpecificationDTO = getAlgorithmSpec(algorithmName);
var exareme2AlgorithmRequestDTO = new Exareme2AlgorithmRequestDTO(uuid, experimentExecutionDTO.algorithm().parameters(), experimentExecutionDTO.algorithm().preprocessing(), exareme2AlgorithmSpecificationDTO);
var exareme2AlgorithmRequestDTO = Exareme2AlgorithmRequestDTO.create(uuid, experimentExecutionDTO.algorithm().parameters(), experimentExecutionDTO.algorithm().preprocessing(), exareme2AlgorithmSpecificationDTO);
String algorithmBody = convertObjectToJsonString(exareme2AlgorithmRequestDTO);
logger.debug("Exareme2 algorithm request, endpoint: " + algorithmEndpoint);
logger.debug("Exareme2 algorithm request, body: " + algorithmBody);
......
......@@ -64,8 +64,8 @@ public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({InternalServerError.class, Exception.class})
public ResponseEntity<ErrorMessage> globalExceptionHandler(Exception ex, WebRequest request) {
logger.error("An unexpected exception occurred: " + ex.getClass() +
"\nMessage: " + ex.getMessage() +
"\nStacktrace: " + Arrays.toString(ex.getStackTrace()).replaceAll(", ", "\n")
" Message: " + ex.getMessage() +
" Stacktrace: " + Arrays.toString(ex.getStackTrace())
);
ErrorMessage message = new ErrorMessage(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
......
......@@ -16,7 +16,7 @@ public class Logger {
}
private void logUserAction(String message, String logLevel){
String logMessage = " User -> " + username + " , " + "Endpoint -> " + endpoint + " , " + "Info -> " + message;
String logMessage = "User -> " + username + " , Endpoint -> " + endpoint + " , Info -> " + message;
switch (logLevel) {
case "ERROR" -> logger.error(logMessage);
......
# Configuration for development purposes
### EMBEDDED SERVER CONFIGURATION ###
server:
servlet:
......@@ -8,15 +7,6 @@ server:
port: 8080
forward-headers-strategy: native
### LOG LEVELS ###
logging:
level:
root: "INFO"
eu:
hbp: "DEBUG"
### DATABASE CONFIGURATION ###
spring:
datasource:
......@@ -51,7 +41,6 @@ spring:
user-name-attribute: preferred_username
issuer-uri: http://172.17.0.1/auth/realms/MIP
### AUTHENTICATION ###
authentication:
enabled: 0
......@@ -59,7 +48,6 @@ authentication:
all_experiments_allowed_claim: research_experiment_all
dataset_claim_prefix: research_dataset_
### EXTERNAL SERVICES ###
services:
algorithmsUpdateInterval: 100
......@@ -68,7 +56,6 @@ services:
attributesUrl: "http://127.0.0.1:5000/data_models_attributes"
cdesMetadataUrl: "http://127.0.0.1:5000/cdes_metadata"
### EXTERNAL FILES ###
# Files are loaded from the resources
files:
......
Configuration:
name: Default
Properties:
Property:
name: log-path
value: "logs"
Appenders:
Console:
name: ConsoleAppender
target: SYSTEM_OUT
PatternLayout:
pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS} - %-5level - %logger{36} - [${env:FEDERATION:-default}] - [${env:SERVICE:-portal-backend}] - %msg%n"
Loggers:
logger:
- name: hbp.mip
level: ${env:LOG_LEVEL:-INFO}
additivity: false # Prevent log propagation to parent loggers
AppenderRef:
- ref: ConsoleAppender
Root:
level: ${env:LOG_LEVEL_FRAMEWORK:-INFO}
AppenderRef:
- ref: ConsoleAppender