fi.evolver.basics.spring.log.MessageLogController Maven / Gradle / Ivy
package fi.evolver.basics.spring.log;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefault;
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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import fi.evolver.basics.spring.http.exception.HttpInternalServerErrorException;
import fi.evolver.basics.spring.http.exception.HttpNotFoundException;
import fi.evolver.basics.spring.log.LogPolicy.Policy;
import fi.evolver.basics.spring.log.entity.MessageLog;
import fi.evolver.basics.spring.log.entity.MessageLogLite;
import fi.evolver.basics.spring.log.model.MessageLogQuery;
import fi.evolver.basics.spring.util.RangeI;
import fi.evolver.basics.spring.util.RangeT;
import fi.evolver.basics.spring.util.filter.FilterValue;
import fi.evolver.utils.format.PrettyPrintUtils;
import fi.evolver.utils.format.PrettyPrintUtils.Format;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
@RestController
@RequestMapping("/log")
public class MessageLogController {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("d.M.yyyy HH:mm:ss.SSS");
private final MessageLogLiteRepository messageLogLiteRepository;
private final MessageLogRepository messageLogRepository;
@Autowired
public MessageLogController(MessageLogLiteRepository messageLogLiteRepository, MessageLogRepository messageLogRepository) {
this.messageLogLiteRepository = messageLogLiteRepository;
this.messageLogRepository = messageLogRepository;
}
@GetMapping
@LogPolicy(Policy.NONE)
@Operation(summary = "Fetches message log list")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "List of message log rows"),
@ApiResponse(responseCode = "400", description = "Invalid request parameters", content = @Content),
@ApiResponse(responseCode = "500", description = "Failed handling request", content = @Content)
})
public Page list(
@ParameterObject MessageLogQuery parameters,
@ParameterObject @PageableDefault(size = 100, direction = Direction.DESC, sort = "startTime") Pageable page) {
return messageLogLiteRepository.search(parameters, page);
}
@GetMapping(path = "/{id}")
@LogPolicy(Policy.NONE)
@Operation(summary = "Fetches message log by ID")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The message log"),
@ApiResponse(responseCode = "400", description = "Invalid request parameters", content = @Content),
@ApiResponse(responseCode = "404", description = "Not found", content = @Content),
@ApiResponse(responseCode = "500", description = "Failed handling request", content = @Content)
})
public MessageLog get(@PathVariable long id) {
return messageLogRepository.findById(id).orElseThrow(HttpNotFoundException::new);
}
@LogPolicy(Policy.NONE)
@Operation(summary = "Fetch request contents of the message")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The request contents"),
@ApiResponse(responseCode = "204", description = "No content"),
@ApiResponse(responseCode = "400", description = "Invalid request parameters", content = @Content),
@ApiResponse(responseCode = "404", description = "Not found", content = @Content),
@ApiResponse(responseCode = "500", description = "Failed handling request", content = @Content)
})
@GetMapping(value = "/{id}/request", produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity request(@PathVariable long id, @RequestParam(defaultValue = "false") boolean pretty) {
return download(id, MessageLog::getRequestMessage, "request", pretty);
}
@LogPolicy(Policy.NONE)
@Operation(summary = "Fetch response contents of the message")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The response contents"),
@ApiResponse(responseCode = "204", description = "No content"),
@ApiResponse(responseCode = "400", description = "Invalid request parameters", content = @Content),
@ApiResponse(responseCode = "404", description = "Not found", content = @Content),
@ApiResponse(responseCode = "500", description = "Failed handling request", content = @Content)
})
@GetMapping(value = "/{id}/response", produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity response(@PathVariable long id, @RequestParam(defaultValue = "false") boolean pretty) {
return download(id, MessageLog::getResponseMessage, "response", pretty);
}
private ResponseEntity download(long id, Function getter, String type, boolean pretty) {
Optional messageLog = messageLogRepository.findById(id);
if (messageLog.isEmpty())
throw new HttpNotFoundException();
byte[] data = getter.apply(messageLog.get());
if (data == null)
return new ResponseEntity<>("".getBytes(), HttpStatus.NO_CONTENT);
Format format;
try (Reader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(data))))) {
format = PrettyPrintUtils.inferFormat(reader);
if (pretty && format != Format.UNKNOWN) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try (Writer writer = new OutputStreamWriter(new GZIPOutputStream(bout), StandardCharsets.UTF_8)) {
PrettyPrintUtils.prettyPrint(reader, writer, format);
}
data = bout.toByteArray();
}
}
catch (IOException e) {
throw new HttpInternalServerErrorException(e);
}
String fileExtension = format.name().toLowerCase();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Encoding", "gzip");
headers.add("Content-Disposition", String.format("attachment; filename=\"message-%s-%s%s.%s\"", messageLog.get().getId(), type, pretty ? "-pretty" : "", fileExtension));
return new ResponseEntity<>(data, headers, HttpStatus.OK);
}
@LogPolicy(Policy.NONE)
@GetMapping(path = "ui")
public CharSequence ui(
MessageLogQuery parameters,
@PageableDefault(size = 100, direction = Direction.DESC, sort = "startTime") Pageable page) {
StringBuilder builder = new StringBuilder();
builder.append("");
builder.append("");
builder.append("");
builder.append("");
builder.append("");
builder.append(
"");
builder.append("");
builder.append("");
builder.append("");
return builder;
}
private static void input(StringBuilder builder, String name, List extends FilterValue>> values) {
input(builder, name, values == null ? null : values.stream().map(Object::toString).collect(Collectors.joining(", ")));
}
private static void input(StringBuilder builder, String name, String value) {
builder.append(" ");
}
private static void input(StringBuilder builder, String name, Optional min, Optional max) {
builder.append(" ");
}
private static String clean(T value) {
return value.toString().strip().replaceAll("'", "");
}
private static void print(StringBuilder builder, MessageLogLite messageLog) {
builder.append("");
builder.append("").append(messageLog.getId()).append(" ");
builder.append("").append(messageLog.getAppVersion()).append(" ");
builder.append("").append(messageLog.getAppServer()).append(" ");
builder.append("").append(messageLog.getStartTime().format(DATE_TIME_FORMATTER)).append(" ");
builder.append("").append(messageLog.getDurationMs()).append(" ");
builder.append("").append(messageLog.getMessageType()).append(" ");
builder.append("").append(messageLog.getProtocol()).append(" ");
builder.append("").append(messageLog.getRequestingSystem()).append(" ");
builder.append("").append(messageLog.getDataDirection() == MessageLog.Direction.INBOUND ? "←" : "→").append(" ");
builder.append("").append(messageLog.getRespondingSystem()).append(" ");
builder.append("").append(messageLog.getStatusCode()).append(" ");
builder.append("")
.append(messageLog.getMessageChainId())
.append(" ");
builder.append("");
if (messageLog.getRequestSize() > 0)
builder.append("");
builder.append(messageLog.getRequestSize());
if (messageLog.getRequestSize() > 0)
builder.append("");
builder.append(" ");
builder.append("");
if (messageLog.getResponseSize() > 0)
builder.append("");
builder.append(messageLog.getResponseSize());
if (messageLog.getResponseSize() > 0)
builder.append("");
builder.append(" ");
builder.append("");
messageLog.getMetadata().forEach((k, v) -> builder.append("- ")
.append("").append(k).append("")
.append(" = ")
.append(v)
.append("
"));
builder.append("
");
builder.append(" \n");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy