Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.github.stickerifier.stickerify.bot;

import static com.github.stickerifier.stickerify.logger.StructuredLogger.REQUEST_DETAILS;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.EXCEPTION_MESSAGE_LOG_KEY;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.FILE_ID_VALUE;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.FILE_PATH_LOG_KEY;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.ORIGINAL_REQUEST_LOG_KEY;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.REQUEST_DETAILS_VALUE;
import static com.github.stickerifier.stickerify.telegram.Answer.CORRUPTED;
import static com.github.stickerifier.stickerify.telegram.Answer.ERROR;
import static com.github.stickerifier.stickerify.telegram.Answer.FILE_ALREADY_VALID;
Expand Down Expand Up @@ -77,7 +81,7 @@ public int process(List<Update> updates) {
updates.forEach(update -> executor.execute(() -> {
if (update.message() != null) {
var request = new TelegramRequest(update.message());
ScopedValue.where(REQUEST_DETAILS, request.toRequestDetails()).run(() -> answer(request));
ScopedValue.where(REQUEST_DETAILS_VALUE, request.toRequestDetails()).run(() -> answer(request));
}
}));

Expand All @@ -86,7 +90,10 @@ public int process(List<Update> updates) {

@Override
public void onException(TelegramException e) {
LOGGER.at(Level.ERROR).setCause(e).addKeyValue("exception_message", e.getMessage()).log("An unexpected failure occurred");
LOGGER.at(Level.ERROR)
.setCause(e)
.addKeyValue(EXCEPTION_MESSAGE_LOG_KEY, e.getMessage())
.log("An unexpected failure occurred");
}

@Override
Expand Down Expand Up @@ -116,7 +123,7 @@ private void answerFile(TelegramRequest request, TelegramFile file) {
if (file == TelegramFile.NOT_SUPPORTED) {
answerText(ERROR, request);
} else if (file.canBeDownloaded()) {
answerFile(request, file.id());
ScopedValue.where(FILE_ID_VALUE, file.id()).run(() -> answerFile(request, file.id()));
} else {
LOGGER.at(Level.INFO).log("Passed-in file is too large");

Expand Down Expand Up @@ -149,7 +156,7 @@ private void answerFile(TelegramRequest request, String fileId) {
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
processFailure(request, e, fileId);
processFailure(request, e);
} finally {
deleteTempFiles(pathsToDelete);
}
Expand All @@ -169,7 +176,7 @@ private File retrieveFile(String fileId) throws TelegramApiException, FileOperat
}
}

private void processFailure(TelegramRequest request, Exception e, String fileId) {
private void processFailure(TelegramRequest request, Exception e) {
if (e instanceof TelegramApiException telegramException) {
boolean replyToUser = processTelegramFailure(telegramException, false);
if (!replyToUser) {
Expand All @@ -178,10 +185,10 @@ private void processFailure(TelegramRequest request, Exception e, String fileId)
}

if (e instanceof CorruptedFileException) {
LOGGER.at(Level.INFO).log("Unable to reply to the request: the file is corrupted");
LOGGER.at(Level.WARN).log("Unable to reply to the request: the file is corrupted");
answerText(CORRUPTED, request);
} else {
LOGGER.at(Level.WARN).setCause(e).addKeyValue("file_id", fileId).log("Unable to process file");
LOGGER.at(Level.ERROR).setCause(e).log("Unable to process file");
answerText(ERROR, request);
}
}
Expand All @@ -206,7 +213,7 @@ private boolean processTelegramFailure(TelegramApiException e, boolean logUnmatc
private void answerText(TelegramRequest request) {
var message = request.message();
if (message.text() == null) {
LOGGER.at(Level.INFO).log("An unhandled message type has been received");
LOGGER.at(Level.INFO).addKeyValue(ORIGINAL_REQUEST_LOG_KEY, message).log("An unhandled message type has been received");
}

answerText(request.getAnswerMessage(), request);
Expand Down Expand Up @@ -241,10 +248,10 @@ private static void deleteTempFiles(Set<Path> pathsToDelete) {
for (var path : pathsToDelete) {
try {
if (!Files.deleteIfExists(path)) {
LOGGER.at(Level.INFO).addKeyValue("file_path", path).log("Unable to delete temp file");
LOGGER.at(Level.INFO).addKeyValue(FILE_PATH_LOG_KEY, path).log("Unable to delete temp file");
}
} catch (IOException e) {
LOGGER.at(Level.ERROR).setCause(e).addKeyValue("file_path", path).log("An error occurred trying to delete temp file");
LOGGER.at(Level.ERROR).setCause(e).addKeyValue(FILE_PATH_LOG_KEY, path).log("An error occurred trying to delete temp file");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,40 @@

public record StructuredLogger(Logger logger) {

public static final ScopedValue<RequestDetails> REQUEST_DETAILS = ScopedValue.newInstance();
public static final ScopedValue<String> MIME_TYPE = ScopedValue.newInstance();
public static final ScopedValue<RequestDetails> REQUEST_DETAILS_VALUE = ScopedValue.newInstance();
public static final ScopedValue<String> FILE_ID_VALUE = ScopedValue.newInstance();
public static final ScopedValue<String> MIME_TYPE_VALUE = ScopedValue.newInstance();

private static final String REQUEST_DETAILS_LOG_KEY = "request_details";
private static final String FILE_ID_LOG_KEY = "file_id";
private static final String MIME_TYPE_LOG_KEY = "mime_type";
public static final String EXCEPTION_MESSAGE_LOG_KEY = "exception_message";
public static final String ORIGINAL_REQUEST_LOG_KEY = "original_request";
public static final String FILE_PATH_LOG_KEY = "file_path";
public static final String STICKER_LOG_KEY = "sticker";

public StructuredLogger(Class<?> clazz) {
this(LoggerFactory.getLogger(clazz));
}

/**
* Creates a {@link LoggingEventBuilder} at the specified level with request details and MIME type information, if set.
* Creates a {@link LoggingEventBuilder} at the specified level enriched with request details,
* file id, and MIME type information when available.
*
* @param level the level of the log
* @return the log builder with context information
*/
public LoggingEventBuilder at(Level level) {
var logBuilder = logger.atLevel(level);

if (REQUEST_DETAILS.isBound()) {
logBuilder = logBuilder.addKeyValue("request_details", REQUEST_DETAILS.get());
if (REQUEST_DETAILS_VALUE.isBound()) {
logBuilder = logBuilder.addKeyValue(REQUEST_DETAILS_LOG_KEY, REQUEST_DETAILS_VALUE.get());
}
if (FILE_ID_VALUE.isBound()) {
logBuilder = logBuilder.addKeyValue(FILE_ID_LOG_KEY, FILE_ID_VALUE.get());
}
if (MIME_TYPE.isBound()) {
logBuilder = logBuilder.addKeyValue("mime_type", MIME_TYPE.get());
if (MIME_TYPE_VALUE.isBound()) {
logBuilder = logBuilder.addKeyValue(MIME_TYPE_LOG_KEY, MIME_TYPE_VALUE.get());
}

return logBuilder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.github.stickerifier.stickerify.media;

import static com.github.stickerifier.stickerify.logger.StructuredLogger.MIME_TYPE;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.FILE_PATH_LOG_KEY;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.MIME_TYPE_VALUE;
import static com.github.stickerifier.stickerify.logger.StructuredLogger.STICKER_LOG_KEY;
import static com.github.stickerifier.stickerify.media.MediaConstraints.MATROSKA_FORMAT;
import static com.github.stickerifier.stickerify.media.MediaConstraints.MAX_ANIMATION_DURATION_SECONDS;
import static com.github.stickerifier.stickerify.media.MediaConstraints.MAX_ANIMATION_FILE_SIZE;
Expand Down Expand Up @@ -67,7 +69,7 @@ public final class MediaHelper {
public static @Nullable File convert(File inputFile) throws Exception {
var mimeType = detectMimeType(inputFile);

return ScopedValue.where(MIME_TYPE, mimeType).call(() -> performConversion(inputFile, mimeType));
return ScopedValue.where(MIME_TYPE_VALUE, mimeType).call(() -> performConversion(inputFile, mimeType));
}

/**
Expand All @@ -81,7 +83,7 @@ private static String detectMimeType(File file) throws MediaException {
try {
return TIKA.detect(file);
} catch (IOException e) {
LOGGER.at(Level.ERROR).setCause(e).addKeyValue("file_name", file.getName()).log("Unable to retrieve MIME type");
LOGGER.at(Level.ERROR).setCause(e).addKeyValue(FILE_PATH_LOG_KEY, file.getPath()).log("Unable to retrieve MIME type");
throw new MediaException(e);
}
}
Expand Down Expand Up @@ -253,7 +255,7 @@ private static boolean isAnimatedStickerCompliant(File file, String mimeType) th
try (var gzipInputStream = new GZIPInputStream(new FileInputStream(file))) {
uncompressedContent = new String(gzipInputStream.readAllBytes(), UTF_8);
} catch (IOException e) {
LOGGER.at(Level.ERROR).setCause(e).addKeyValue("file_name", file.getName()).log("Unable to retrieve gzip content");
LOGGER.at(Level.ERROR).setCause(e).addKeyValue(FILE_PATH_LOG_KEY, file.getPath()).log("Unable to retrieve gzip content");
}

try {
Expand All @@ -267,7 +269,7 @@ private static boolean isAnimatedStickerCompliant(File file, String mimeType) th
}
}

LOGGER.at(Level.WARN).addKeyValue("sticker", sticker).log("The animated sticker doesn't meet Telegram's requirements");
LOGGER.at(Level.WARN).addKeyValue(STICKER_LOG_KEY, sticker).log("The animated sticker doesn't meet Telegram's requirements");
} catch (JsonSyntaxException _) {
LOGGER.at(Level.INFO).log("The archive isn't an animated sticker");
}
Expand Down Expand Up @@ -448,7 +450,7 @@ private static File createTempFile(String fileExtension) throws FileOperationExc
private static void deleteFile(File file) throws FileOperationException {
try {
if (!Files.deleteIfExists(file.toPath())) {
LOGGER.at(Level.INFO).addKeyValue("file_path", file.toPath()).log("Unable to delete file");
LOGGER.at(Level.INFO).addKeyValue(FILE_PATH_LOG_KEY, file.toPath()).log("Unable to delete file");
}
} catch (IOException e) {
throw new FileOperationException("An error occurred deleting the file", e);
Expand Down Expand Up @@ -493,11 +495,11 @@ private static File convertToWebm(File file) throws MediaException, InterruptedE
}
throw new MediaException("FFmpeg two-pass conversion failed", e);
} finally {
var logFileName = logPrefix + "-0.log";
var logFilePath = logPrefix + "-0.log";
try {
deleteFile(new File(logFileName));
deleteFile(new File(logFilePath));
} catch (FileOperationException e) {
LOGGER.at(Level.WARN).setCause(e).addKeyValue("file_name", logFileName).log("Could not delete log file");
LOGGER.at(Level.WARN).setCause(e).addKeyValue(FILE_PATH_LOG_KEY, logFilePath).log("Could not delete log file");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public enum Answer {
If you think it should have worked, please report the issue on [Github](https://github.com/Stickerifier/Stickerify/issues/new/choose)\\.
""", true),
CORRUPTED("""
The conversion was unsuccessful: the video might be corrupted and it cannot be processed\\.
The conversion was unsuccessful: the media might be corrupted and it cannot be processed\\.
If you think it should have worked, please report the issue on [Github](https://github.com/Stickerifier/Stickerify/issues/new/choose)\\.
""", true),
Expand Down
Loading