Refactor of History module (#184)
Co-authored-by: widlam <mikolaj.widla@gmail.com> Co-authored-by: Adam Bem <adam.bem@zoho.eu> Reviewed-on: #184 Reviewed-by: Adam Bem <bema@noreply.example.com> Co-authored-by: Mikolaj Widla <widlam@noreply.example.com> Co-committed-by: Mikolaj Widla <widlam@noreply.example.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.1.RELEASE</version>
|
||||
<version>2.7.11</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
<jedis.version>3.3.0</jedis.version>
|
||||
<logback-redis-appender.version>1.1.6</logback-redis-appender.version>
|
||||
<assertj.version>3.16.1</assertj.version>
|
||||
<mapstruct.version>1.3.1.Final</mapstruct.version>
|
||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||
<docker.image.prefix>Release11</docker.image.prefix>
|
||||
<docker.image.name>${project.artifactId}</docker.image.name>
|
||||
<lombok.version>1.18.26</lombok.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -57,21 +58,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.cwbase</groupId>
|
||||
<artifactId>logback-redis-appender</artifactId>
|
||||
<version>${logback-redis-appender.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>${jedis.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jettison</groupId>
|
||||
<artifactId>jettison</artifactId>
|
||||
<version>1.4.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -101,6 +87,11 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</dependency>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs>
|
||||
<compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.r11.tools.config;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
|
||||
/**
|
||||
* Class containing configuration for Redis db client
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRedisRepositories
|
||||
@PropertySource("classpath:data-access.properties")
|
||||
public class RedisConfig {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Bean of JedisPool - the Redis client. It stores requests in "the pool" and then fires them at Redis.
|
||||
* It's considered super lightweight and fast client variant
|
||||
* @return lightweight client of the Redis - the JedisPool
|
||||
*/
|
||||
@Bean
|
||||
JedisPool jedisPool(){
|
||||
final JedisPool pool = new JedisPool(environment.getProperty("redis.host"),
|
||||
Integer.parseInt(environment.getProperty("redis.port")));
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean of a factory for connenction object.
|
||||
* It's initialized with Redis db url property and is fed to other methods.
|
||||
* @return the factory for RedisTemplates
|
||||
*/
|
||||
@Bean
|
||||
JedisConnectionFactory jedisConnectionFactory() {
|
||||
RedisStandaloneConfiguration redisStandaloneConfiguration =
|
||||
new RedisStandaloneConfiguration(Objects.requireNonNull(environment.getProperty("redis.host")),
|
||||
Integer.parseInt(Objects.requireNonNull(environment.getProperty("redis.port"))));
|
||||
return new JedisConnectionFactory(redisStandaloneConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* RedisTemplate is the tool to store and retrieve given type (object) of hash from the database.
|
||||
* It's like you could store your Java object by just naming it inside database. You might thing about it
|
||||
* as of DAO.
|
||||
* @return RedisTemplate the redis dao.
|
||||
*/
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(jedisConnectionFactory());
|
||||
redisTemplate.setExposeConnection(true);
|
||||
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import com.r11.tools.repository.MockedResponseRepository;
|
||||
import com.r11.tools.repository.RequestHistoryRepository;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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 java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Based on configuration deletes all outdated messages and history records from database.
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
public class RetentionConfiguration {
|
||||
|
||||
private final MockedResponseRepository responseRepository;
|
||||
private final RequestHistoryRepository historyRepository;
|
||||
private final RetentionConfigurationProperties retentionProperties;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
|
||||
|
||||
public RetentionConfiguration(MockedResponseRepository responseRepository,
|
||||
RequestHistoryRepository historyRepository,
|
||||
RetentionConfigurationProperties retentionProperties){
|
||||
this.historyRepository = historyRepository;
|
||||
this.responseRepository = responseRepository;
|
||||
this.retentionProperties = retentionProperties;
|
||||
}
|
||||
@Scheduled(fixedDelayString = "#{${retention.retention-cooldown} * 60000 }")
|
||||
@Async
|
||||
public void deleteMessagesAndHistoryRecords(){
|
||||
log.info("OUTDATED MESSAGES AND HISTORY RECORDS DELETED!");
|
||||
responseRepository
|
||||
.findAll()
|
||||
.iterator()
|
||||
.forEachRemaining( mockedMessage -> {
|
||||
if (mockedMessage.getCreatedAt().plusMinutes(retentionProperties.getMinutesToDeleteMessage()).isBefore(LocalDateTime.now())){
|
||||
responseRepository.delete(mockedMessage);
|
||||
}
|
||||
} );
|
||||
|
||||
historyRepository
|
||||
.findAll()
|
||||
.iterator()
|
||||
.forEachRemaining(
|
||||
historyRecord -> {
|
||||
if (historyRecord.getDateTimeStamp().plusMinutes(retentionProperties.getMinutesToDeleteHistoryRecord()).isBefore(LocalDateTime.now())){
|
||||
historyRepository.delete(historyRecord);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.validation.constraints.Positive;
|
||||
|
||||
/**
|
||||
* Store all properties needed to change a retention in {@link RetentionConfiguration}
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "retention")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RetentionConfigurationProperties {
|
||||
@Positive
|
||||
private Integer minutesToDeleteMessage;
|
||||
@Positive
|
||||
private Integer minutesToDeleteHistoryRecord;
|
||||
@Positive
|
||||
private Integer retentionCooldown;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.r11.tools.configuration;
|
||||
|
||||
import com.r11.tools.interceptor.IncomingMockRequestInterceptor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* Configuration for {@link IncomingMockRequestInterceptor}
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class WebConfig implements WebMvcConfigurer{
|
||||
|
||||
private final IncomingMockRequestInterceptor requestInterceptor;
|
||||
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor( requestInterceptor )
|
||||
.addPathPatterns("/api/mock/r/**");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.r11.tools.model.EventRequestDto;
|
||||
import com.r11.tools.service.EtrackService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* It's the REST api for {@link com.r11.tools.model.Event}
|
||||
* @author Gabriel Modzelewski
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/event")
|
||||
@AllArgsConstructor
|
||||
public class EventController {
|
||||
private final EtrackService service;
|
||||
|
||||
/**
|
||||
* Returns the list of Events in given time bracket.
|
||||
* The list of objects is received via {@link EventRequestDto}, which contains time brackets,
|
||||
* as well as the key - uuid.
|
||||
* @param event EventRequestDto object that contains data needed to query the database
|
||||
* @return list of {@link com.r11.tools.model.Event}
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseEntity filterHistory(@RequestBody EventRequestDto event){
|
||||
return new ResponseEntity(service.getEventsByDateTimeAndBusinessKeys(event), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of Events of last 24h from given date.
|
||||
* @param uuid unique id of message list
|
||||
* @param messageId unique id of message in message list
|
||||
* @return list of {@link com.r11.tools.model.Event}
|
||||
*/
|
||||
@GetMapping(path = "/{uuid}/{messageId}")
|
||||
public ResponseEntity getLastDay(@PathVariable UUID uuid,
|
||||
@PathVariable Integer messageId){
|
||||
LocalDateTime requestTime = LocalDateTime.now();
|
||||
LocalDateTime dayBeforeRequest = requestTime.minusDays(1L);
|
||||
EventRequestDto eventRequestDto = EventRequestDto.builder()
|
||||
.clientUUID(uuid)
|
||||
.mockedResponseId(messageId)
|
||||
.localDateTimeFrom(dayBeforeRequest)
|
||||
.localDateTimeTo(requestTime)
|
||||
.build();
|
||||
return new ResponseEntity(service.getEventsByDateTimeAndBusinessKeys(eventRequestDto), HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ package com.r11.tools.controller;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
import com.r11.tools.service.KlausService;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import com.r11.tools.utilis.TrackingClient;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -18,17 +19,19 @@ import java.util.*;
|
||||
/**
|
||||
* Returns the homepage and provides the api for javascript async requests.
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/mock")
|
||||
@AllArgsConstructor
|
||||
@CrossOrigin(origins = "*")
|
||||
public class MockController {
|
||||
private final KlausService klausService;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public void errorHandler(Exception ex){
|
||||
log.error(ex.getStackTrace());
|
||||
log.error(Arrays.toString(ex.getStackTrace()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,22 +178,14 @@ public class MockController {
|
||||
/**
|
||||
* It's one of the most important features - the bread and butter of the Mocked Service. It's link that allows
|
||||
* to receive mocked response from the server and use it to mock!
|
||||
* @param requestEntity Logs the data of request
|
||||
* @param clientUUID the key-uuid of given set of messages
|
||||
* @param mockedResponseId unique id of given message
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/r/{clientUUID}/{mockedResponseId}")
|
||||
public ResponseEntity getMockedResponse(RequestEntity<String> requestEntity,
|
||||
@RequestMapping(value = "/r/{clientUUID}/{mockedResponseId}")
|
||||
public ResponseEntity getMockedResponse(
|
||||
@PathVariable UUID clientUUID,
|
||||
@PathVariable int mockedResponseId) {
|
||||
TrackingClient.setBusinessKeys(Map.of(BusinessKey.INTERFACE_NAME, "getMockedResponse - request",
|
||||
BusinessKey.CLIENT_UUID, String.valueOf(clientUUID),
|
||||
BusinessKey.MESSAGE_ID, String.valueOf(mockedResponseId)));
|
||||
// log.info(requestEntity.toString().replaceAll("\"", "\\\\\"").substring(1).replaceAll("\n",""));
|
||||
TrackingClient.setBusinessKeys(Map.of(BusinessKey.INTERFACE_NAME, "getMockedResponse - response",
|
||||
BusinessKey.CLIENT_UUID, String.valueOf(clientUUID),
|
||||
BusinessKey.MESSAGE_ID, String.valueOf(mockedResponseId)));
|
||||
MockedMessageDto mockedMessageDto = klausService.getMockedResponse(clientUUID, mockedResponseId);
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
if (mockedMessageDto.getHttpHeaders() != null) mockedMessageDto.getHttpHeaders().forEach(httpHeaders::set);
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
|
||||
@@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@ControllerAdvice
|
||||
@CrossOrigin(origins = "*")
|
||||
public class MvcExceptionHandler {
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.r11.tools.controller;
|
||||
|
||||
import com.r11.tools.mappers.RequestHistoryMapper;
|
||||
import com.r11.tools.model.HistoryRequestModel;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.service.RequestHistoryService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* It's the REST api for {@link RequestHistory}
|
||||
* @author Gabriel Modzelewski
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(path = "/api/event")
|
||||
@AllArgsConstructor
|
||||
@CrossOrigin(origins = "*")
|
||||
public class RequestHistoryController {
|
||||
private final RequestHistoryService service;
|
||||
private final RequestHistoryMapper mapper;
|
||||
|
||||
/**
|
||||
* Returns the list of Events in given time bracket.
|
||||
* The list of objects is received via {@link RequestHistoryDTO}, which contains time brackets,
|
||||
* as well as the key - uuid.
|
||||
* @param historyRequestModel EventRequestDto object that contains data needed to query the database
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseEntity<List<RequestHistoryDTO>> filterHistory(@RequestBody HistoryRequestModel historyRequestModel){
|
||||
return ResponseEntity.ok(
|
||||
service.getHistoryRecordsBetweenDatesAndByUUIDAndMessageId(historyRequestModel)
|
||||
.stream()
|
||||
.map(mapper::requestHistoryToRequestHistoryDTO)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of Events of last 24h from given date.
|
||||
* @param uuid unique id of message list
|
||||
* @param messageId unique id of message in message list
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
@GetMapping(path = "/{uuid}/{messageId}")
|
||||
public ResponseEntity<List<RequestHistoryDTO>> getLastDay(@PathVariable UUID uuid,
|
||||
@PathVariable Integer messageId){
|
||||
LocalDateTime requestTime = LocalDateTime.now();
|
||||
LocalDateTime dayBeforeRequest = requestTime.minusDays(1L);
|
||||
List<RequestHistoryDTO> requestHistory = service.getHistoryRecordsBetweenDatesAndByUUIDAndMessageId(
|
||||
HistoryRequestModel.builder()
|
||||
.localDateTimeFrom(dayBeforeRequest)
|
||||
.localDateTimeTo(requestTime)
|
||||
.clientUUID(uuid)
|
||||
.mockedResponseId(messageId)
|
||||
.build()
|
||||
).stream()
|
||||
.map(mapper::requestHistoryToRequestHistoryDTO)
|
||||
.collect(Collectors.toList());
|
||||
return ResponseEntity.ok(requestHistory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.r11.tools.interceptor;
|
||||
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.service.RequestHistoryService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* Interceptor that gets needed data from HttpRequest, and saves it to history
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class IncomingMockRequestInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final RequestHistoryService historyService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse response, Object handler){
|
||||
Map<String,String> headers = getHeadersFromHttpRequest(httpRequest);
|
||||
Map<String,String> pathVariable = getPathVariablesFromHttpRequest(httpRequest);
|
||||
String requestBody = getRequestBodyFromHttpRequest(httpRequest);
|
||||
|
||||
RequestHistoryDTO historyDTO = RequestHistoryDTO.builder()
|
||||
.httpMethod(HttpMethod.valueOf(httpRequest.getMethod()))
|
||||
.headers( headers )
|
||||
.messageID(Integer.valueOf(pathVariable.get("mockedResponseId")))
|
||||
.clientUUID(UUID.fromString(pathVariable.get("clientUUID")))
|
||||
.dateTimeStamp(LocalDateTime.now())
|
||||
.requestBody(requestBody)
|
||||
.build();
|
||||
historyService.saveRequest(historyDTO);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Map<String,String> getHeadersFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
Set<String> headersName = StreamSupport.stream(
|
||||
Spliterators.spliteratorUnknownSize(
|
||||
httpRequest.getHeaderNames().asIterator(),
|
||||
Spliterator.ORDERED
|
||||
), false
|
||||
).collect(Collectors.toSet());
|
||||
|
||||
return headersName.stream()
|
||||
.collect(Collectors.toMap(
|
||||
value -> value,
|
||||
httpRequest::getHeader
|
||||
));
|
||||
}
|
||||
|
||||
private Map<String,String> getPathVariablesFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
return (Map<String, String>) httpRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
}
|
||||
|
||||
private String getRequestBodyFromHttpRequest( HttpServletRequest httpRequest ){
|
||||
HttpServletRequest wrappedRequest = new ContentCachingRequestWrapper(httpRequest);
|
||||
try {
|
||||
return StreamUtils.copyToString(wrappedRequest.getInputStream(), Charset.defaultCharset());
|
||||
} catch (IOException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import org.mapstruct.*;
|
||||
public interface MockedMessageMapper {
|
||||
@Mapping( target = "compositePrimaryKey", expression = "java(mockedMessageDto.getClientUUID() + \"_\"" +
|
||||
" + mockedMessageDto.getMockedResponseId())")
|
||||
@Mapping( target = "createdAt" , expression = "java(java.time.LocalDateTime.now())")
|
||||
MockedMessage mockedMessageDtoToMockedMessage(MockedMessageDto mockedMessageDto);
|
||||
MockedMessageDto mockedMessageToMockedMessageDto(MockedMessage mockedMessage);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.r11.tools.mappers;
|
||||
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
/**
|
||||
* Map between DTO and Entity
|
||||
*
|
||||
* @author Mikołaj Widła
|
||||
*
|
||||
*/
|
||||
|
||||
@Mapper
|
||||
public interface RequestHistoryMapper {
|
||||
|
||||
@Mapping(target = "id", expression = "java(null)")
|
||||
@Mapping(target = "clientUUID", expression = "java(requestHistoryDTO.getClientUUID().toString())")
|
||||
RequestHistory requestHistoryDTOToRequestHistory(RequestHistoryDTO requestHistoryDTO);
|
||||
@Mapping(target = "clientUUID", expression = "java(java.util.UUID.fromString(requestHistory.getClientUUID()))")
|
||||
RequestHistoryDTO requestHistoryToRequestHistoryDTO(RequestHistory requestHistory);
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Pojo class for Event entity
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Event implements Comparable<Event>{
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss")
|
||||
private LocalDateTime dateTimeStamp;
|
||||
@Nullable
|
||||
private String interfaceName;
|
||||
@Nullable
|
||||
private String clientUUID;
|
||||
@Nullable
|
||||
private Integer messageId;
|
||||
private String thread;
|
||||
private String level;
|
||||
@Nullable
|
||||
private String message;
|
||||
|
||||
@Override
|
||||
public int compareTo(Event o) {
|
||||
return this.getDateTimeStamp().compareTo(o.getDateTimeStamp()) * -1;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Pojo for history query request. Contains information necessary to obtain {@link Event} list
|
||||
* @author Rafał Żukowicz
|
||||
* Represents all data needed to get HistoryRecord from database
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EventRequestDto {
|
||||
public class HistoryRequestModel {
|
||||
|
||||
private UUID clientUUID;
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
|
||||
@@ -2,6 +2,7 @@ package com.r11.tools.model;
|
||||
|
||||
import com.r11.tools.model.constraints.HttpCode;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.validation.constraints.Positive;
|
||||
@@ -34,6 +35,7 @@ public class MockedMessage implements Serializable {
|
||||
private Map<String, String> httpHeaders;
|
||||
@HttpCode
|
||||
private Integer httpStatus;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
import org.springframework.data.redis.core.index.Indexed;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Pojo class for Event entity
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RedisHash("mockHistory")
|
||||
public class RequestHistory implements Comparable<RequestHistory>, Serializable {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
@DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss")
|
||||
private LocalDateTime dateTimeStamp;
|
||||
@Indexed
|
||||
private String clientUUID;
|
||||
@Indexed
|
||||
private Integer messageID;
|
||||
private Map<String,String> headers;
|
||||
private HttpMethod httpMethod;
|
||||
private String requestBody;
|
||||
|
||||
@Override
|
||||
public int compareTo(RequestHistory o) {
|
||||
return this.getDateTimeStamp().compareTo(o.getDateTimeStamp()) * -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.r11.tools.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Pojo for history query request. Contains information necessary to obtain {@link RequestHistory} list
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RequestHistoryDTO {
|
||||
|
||||
private UUID clientUUID;
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
|
||||
private LocalDateTime dateTimeStamp;
|
||||
private Integer messageID;
|
||||
private Map<String,String> headers;
|
||||
private HttpMethod httpMethod;
|
||||
private String requestBody;
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Event entity dao interface
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public interface EventRepository {
|
||||
List<Event> findEvents(LocalDateTime localDateTimeFrom, LocalDateTime localDateTimeTo,
|
||||
Map<BusinessKey, String> businessKeys);
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import static com.r11.tools.utilis.RedisAppender.LOG_PREFIX;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
|
||||
/**
|
||||
* Builds Event list based on logs created via {@link com.r11.tools.utilis.TrackingClient} and {@link com.r11.tools.utilis.RedisAppender}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@AllArgsConstructor
|
||||
public class EventRepositoryImpl implements EventRepository {
|
||||
private final JedisPool jedisPool;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Creates list of {@link Event} based on {@link com.r11.tools.model.EventRequestDto} data via searching logs
|
||||
* @param localDateTimeFrom date from which logs are retrieved
|
||||
* @param localDateTimeTo date to which logs are retrieved
|
||||
* @param businessKeys set keys for redis values
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<Event> findEvents(LocalDateTime localDateTimeFrom, LocalDateTime localDateTimeTo,
|
||||
Map<BusinessKey, String> businessKeys) {
|
||||
List<String> eventStrings = findEventsBetweenDates(localDateTimeFrom.toLocalDate(), localDateTimeTo.toLocalDate());
|
||||
if (businessKeys.size() > 0) {
|
||||
eventStrings = businessKeysFilter(eventStrings, businessKeys);
|
||||
}
|
||||
List<Event> events = parseEvents(eventStrings);
|
||||
if (localDateTimeFrom.toLocalTime() != LocalTime.MIN) {
|
||||
events = events.stream().filter(event -> event.getDateTimeStamp().compareTo(localDateTimeFrom) >= 0)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return events.stream().filter(event -> event.getDateTimeStamp().compareTo(localDateTimeTo) <= 0)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns logs between given dates
|
||||
* @param localDateFrom date from which logs are retrieved
|
||||
* @param localDateTo date to which logs are retrieved
|
||||
* @return
|
||||
*/
|
||||
private List<String> findEventsBetweenDates(LocalDate localDateFrom, LocalDate localDateTo) {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
return localDateFrom.datesUntil(localDateTo.plusDays(1)).map(day -> LOG_PREFIX + day.toString())
|
||||
.map(key -> jedis.lrange(key, 0, -1)).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters keys so only the ones queried are retirned
|
||||
* @param events list of logs
|
||||
* @param businessKeys set keys for redis values
|
||||
* @return filtered list of logs
|
||||
*/
|
||||
private List<String> businessKeysFilter(List<String> events, Map<BusinessKey, String> businessKeys) {
|
||||
for (Map.Entry<BusinessKey, String> entry : businessKeys.entrySet()) {
|
||||
String stringPattern = entry.getKey().getReasonPhrase()+ "\"" + ":" + "\"" + entry.getValue() + "\"";
|
||||
events = events.stream().filter(s -> s.contains(stringPattern)).collect(Collectors.toList());
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses list of logs into list of {@link Event}
|
||||
* @param eventStrings list of logs
|
||||
* @return list of {@link Event}
|
||||
*/
|
||||
private List<Event> parseEvents(List<String> eventStrings) {
|
||||
List<Event> events = new ArrayList<>();
|
||||
for (String eventString : eventStrings) {
|
||||
eventString = eventString.replaceAll("\\R", "");
|
||||
try {
|
||||
events.add(objectMapper.readValue(eventString, Event.class));
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return events;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.r11.tools.repository;
|
||||
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* History Record entity dao interface
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Repository
|
||||
@Transactional
|
||||
public interface RequestHistoryRepository extends CrudRepository<RequestHistory,String> {
|
||||
List<RequestHistory> findAllByClientUUIDAndMessageID(
|
||||
String clientUUID,
|
||||
Integer messageID);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.model.EventRequestDto;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Spring service interface for {@link com.r11.tools.controller.EventController}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
public interface EtrackService {
|
||||
/**
|
||||
* Searches for {@link Event} objects between date brackets
|
||||
* @param eventsDto object containing required data for request
|
||||
* @return list of {@link Event}
|
||||
*/
|
||||
List<Event> getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.model.Event;
|
||||
import com.r11.tools.model.EventRequestDto;
|
||||
import com.r11.tools.repository.EventRepository;
|
||||
import com.r11.tools.utilis.BusinessKey;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Spring Service for {@link com.r11.tools.controller.EventController}. Contains logic required for quering
|
||||
* the database for {@link Event} objects
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class EtrackServiceImpl implements EtrackService {
|
||||
|
||||
private final EventRepository eventRepository;
|
||||
|
||||
/**
|
||||
* Adds {@link BusinessKey} to {@link EventRequestDto}
|
||||
* in order to create query via{@link com.r11.tools.repository.EventRepositoryImpl}
|
||||
* @param eventsDto object containing required data for request
|
||||
* @return list of {@link Event}
|
||||
*/
|
||||
@Override
|
||||
public List<Event> getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto) {
|
||||
Map<BusinessKey, String> businessKeys = new HashMap<>();
|
||||
businessKeys.put(BusinessKey.CLIENT_UUID, eventsDto.getClientUUID().toString());
|
||||
if (eventsDto.getMockedResponseId() != null){
|
||||
businessKeys.put(BusinessKey.MESSAGE_ID, String.valueOf(eventsDto.getMockedResponseId()));
|
||||
}
|
||||
List<Event> events = eventRepository.findEvents(eventsDto.getLocalDateTimeFrom(), eventsDto.getLocalDateTimeTo(),
|
||||
businessKeys);
|
||||
Collections.sort(events);
|
||||
return events;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r11.tools.mappers.MockedMessageMapper;
|
||||
import com.r11.tools.model.MockedMessage;
|
||||
import com.r11.tools.model.MockedMessageDto;
|
||||
@@ -13,6 +12,7 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
@@ -30,7 +30,6 @@ public class KlausServiceImpl implements KlausService {
|
||||
private final MockedMessageMapper mockedMessageMapper;
|
||||
private final Logger log = LogManager.getRootLogger();
|
||||
private final MockedResponseRepository mockedResponseRepository;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Removes message of given id in given key-uuid set
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.controller.RequestHistoryController;
|
||||
import com.r11.tools.model.HistoryRequestModel;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Spring service interface for {@link RequestHistoryController}
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@Service
|
||||
public interface RequestHistoryService {
|
||||
/**
|
||||
* Searches for {@link RequestHistory} objects between date brackets
|
||||
* @param historyRequestModel object containing required data for request
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
List<RequestHistory> getHistoryRecordsBetweenDatesAndByUUIDAndMessageId(HistoryRequestModel historyRequestModel);
|
||||
void saveRequest(RequestHistoryDTO requestDTO);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.r11.tools.service;
|
||||
|
||||
import com.r11.tools.controller.RequestHistoryController;
|
||||
import com.r11.tools.mappers.RequestHistoryMapper;
|
||||
import com.r11.tools.model.HistoryRequestModel;
|
||||
import com.r11.tools.model.RequestHistory;
|
||||
import com.r11.tools.model.RequestHistoryDTO;
|
||||
import com.r11.tools.repository.RequestHistoryRepository;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Spring Service for {@link RequestHistoryController}. Contains logic required for quering
|
||||
* the database for {@link RequestHistory} objects
|
||||
* @author Rafał Żukowicz
|
||||
* @author Mikołaj Widła
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class RequestHistoryServiceImpl implements RequestHistoryService {
|
||||
|
||||
private final RequestHistoryRepository repository;
|
||||
private final RequestHistoryMapper requestMapper;
|
||||
|
||||
/**
|
||||
* in order to create query via{@link com.r11.tools.repository.RequestHistoryRepository}
|
||||
* @param historyRequestModel object containing required data for request
|
||||
* @return list of {@link RequestHistory}
|
||||
*/
|
||||
@Override
|
||||
public List<RequestHistory> getHistoryRecordsBetweenDatesAndByUUIDAndMessageId(HistoryRequestModel historyRequestModel) {
|
||||
List<RequestHistory> history = repository.findAllByClientUUIDAndMessageID(
|
||||
historyRequestModel.getClientUUID().toString(),
|
||||
historyRequestModel.getMockedResponseId()
|
||||
);
|
||||
Collections.sort(history);
|
||||
|
||||
return history.stream()
|
||||
.filter( historyRecord -> historyRecord
|
||||
.getDateTimeStamp()
|
||||
.isAfter(historyRequestModel.getLocalDateTimeFrom())
|
||||
).filter(
|
||||
historyRecord-> historyRecord
|
||||
.getDateTimeStamp()
|
||||
.isBefore(historyRequestModel.getLocalDateTimeTo())
|
||||
)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRequest(RequestHistoryDTO requestDTO) {
|
||||
repository.save(requestMapper.requestHistoryDTOToRequestHistory(requestDTO));
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.r11.tools.utilis;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
/**
|
||||
* Enum of keys for redis database.
|
||||
* @author Rafał Żukowicz
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public enum BusinessKey {
|
||||
INTERFACE_NAME("interfaceName"),
|
||||
CLIENT_UUID("clientUUID"),
|
||||
MESSAGE_ID("messageId");
|
||||
|
||||
private final String phrase;
|
||||
|
||||
/**
|
||||
* Returns string value of given enum variant
|
||||
* @return string value of enum
|
||||
*/
|
||||
public String getReasonPhrase() {
|
||||
return this.phrase;
|
||||
}
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
package com.r11.tools.utilis;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.Layout;
|
||||
import ch.qos.logback.core.UnsynchronizedAppenderBase;
|
||||
import com.cwbase.logback.AdditionalField;
|
||||
import com.cwbase.logback.JSONEventLayout;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.Protocol;
|
||||
|
||||
/**
|
||||
* Class is used to insert logs directly to Redis. {@link com.release11.klaus.repository.EventRepositoryImpl} is using those logs.
|
||||
* @author Rafał Żukowicz
|
||||
* @author Gabriel Modzelewski
|
||||
*/
|
||||
public class RedisAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
|
||||
|
||||
JedisPool pool;
|
||||
JSONEventLayout jsonlayout;
|
||||
Layout<ILoggingEvent> layout;
|
||||
String host = "localhost";
|
||||
int port = Protocol.DEFAULT_PORT;
|
||||
String key = null;
|
||||
int timeout = Protocol.DEFAULT_TIMEOUT;
|
||||
String password = null;
|
||||
int database = Protocol.DEFAULT_DATABASE;
|
||||
|
||||
public static final String LOG_PREFIX = "logstash_";
|
||||
|
||||
|
||||
public RedisAppender() {
|
||||
jsonlayout = new JSONEventLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends JedisPool by another log
|
||||
* @param event object containing log info
|
||||
*/
|
||||
@Override
|
||||
protected void append(ILoggingEvent event) {
|
||||
Jedis client = pool.getResource();
|
||||
try {
|
||||
String json = layout == null ? jsonlayout.doLayout(event) : layout.doLayout(event);
|
||||
key = LOG_PREFIX + LocalDate.now();
|
||||
client.rpush(key, json);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (client != null) {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSource() {
|
||||
return jsonlayout.getSource();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSource(String source) {
|
||||
jsonlayout.setSource(source);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSourceHost() {
|
||||
return jsonlayout.getSourceHost();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSourceHost(String sourceHost) {
|
||||
jsonlayout.setSourceHost(sourceHost);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSourcePath() {
|
||||
return jsonlayout.getSourcePath();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setSourcePath(String sourcePath) {
|
||||
jsonlayout.setSourcePath(sourcePath);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getTags() {
|
||||
if (jsonlayout.getTags() != null) {
|
||||
Iterator<String> i = jsonlayout.getTags().iterator();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (i.hasNext()) {
|
||||
sb.append(i.next());
|
||||
if (i.hasNext()) {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setTags(String tags) {
|
||||
if (tags != null) {
|
||||
String[] atags = tags.split(",");
|
||||
jsonlayout.setTags(Arrays.asList(atags));
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getType() {
|
||||
return jsonlayout.getType();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setType(String type) {
|
||||
jsonlayout.setType(type);
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public void setDatabase(int database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setMdc(boolean flag) {
|
||||
jsonlayout.setProperties(flag);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getMdc() {
|
||||
return jsonlayout.getProperties();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setLocation(boolean flag) {
|
||||
jsonlayout.setLocationInfo(flag);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getLocation() {
|
||||
return jsonlayout.getLocationInfo();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setCallerStackIndex(int index) {
|
||||
jsonlayout.setCallerStackIdx(index);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getCallerStackIndex() {
|
||||
return jsonlayout.getCallerStackIdx();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void addAdditionalField(AdditionalField p) {
|
||||
jsonlayout.addAdditionalField(p);
|
||||
}
|
||||
|
||||
public Layout<ILoggingEvent> getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void setLayout(Layout<ILoggingEvent> layout) {
|
||||
this.layout = layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts new instance of JedisPool
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
|
||||
config.setTestOnBorrow(true);
|
||||
pool = new JedisPool(config, host, port, timeout, password, database);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops and destroys JedisPool object
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
pool.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.r11.tools.utilis;
|
||||
|
||||
import java.util.Map;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
/**
|
||||
* This static class has one purpose and one purpose only. It logs data about incomming requests.
|
||||
* The data from logs is received via {@link com.release11.klaus.repository.EventRepositoryImpl}
|
||||
* @author Rafał Żukowski
|
||||
*/
|
||||
public final class TrackingClient {
|
||||
|
||||
/**
|
||||
* Logs data inside the given map
|
||||
* @param businessKeysMap map containing all the information about incomming request
|
||||
*/
|
||||
public static void setBusinessKeys(Map<BusinessKey, String> businessKeysMap){
|
||||
for (Map.Entry<BusinessKey, String> entry : businessKeysMap.entrySet()) {
|
||||
MDC.put(entry.getKey().getReasonPhrase(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -5,3 +5,12 @@ spring.mvc.view.suffix=.html
|
||||
logging.level.root=INFO
|
||||
logging.level.org.springframework.web=INFO
|
||||
logging.level.com.release11=INFO
|
||||
|
||||
#database:
|
||||
spring.redis.host=redis
|
||||
spring.redis.port=6379
|
||||
|
||||
#retention
|
||||
retention.minutes-to-delete-message=120
|
||||
retention.minutes-to-delete-history-record=1440
|
||||
retention.retention-cooldown=1440
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
redis.host = redis
|
||||
redis.port = 6379
|
||||
@@ -2,25 +2,8 @@
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||
<property name="HOME_LOG" value="/log/mockServices.log"/>
|
||||
<!--https://github.com/kmtong/logback-redis-appender-->
|
||||
<appender name="LOGSTASH" class="com.r11.tools.utilis.RedisAppender">
|
||||
<host>redis</host>
|
||||
<port>6379</port>
|
||||
<key>logstash</key>
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<!--https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html-->
|
||||
<Pattern>
|
||||
{"dateTimeStamp" : "%d{yyyy-MM-dd}T%d{HH:mm:ss}", "eventId":"%X{eventId}", "interfaceName":"%X{interfaceName}", "clientUUID":"%X{clientUUID}", "messageId":"%X{messageId}", "thread":"%t","level":"%-5level", "message":"%msg"}%n
|
||||
</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<appender-ref ref="LOGSTASH" />
|
||||
</appender>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${HOME_LOG}</file>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>logs/mockServices.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
@@ -34,7 +17,6 @@
|
||||
</appender>
|
||||
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="ASYNC" />
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
|
||||
Reference in New Issue
Block a user