diff --git a/src/main/java/com/github/stickerifier/stickerify/bot/Stickerify.java b/src/main/java/com/github/stickerifier/stickerify/bot/Stickerify.java index 2aa16d58..de5fb590 100644 --- a/src/main/java/com/github/stickerifier/stickerify/bot/Stickerify.java +++ b/src/main/java/com/github/stickerifier/stickerify/bot/Stickerify.java @@ -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; @@ -77,7 +81,7 @@ public int process(List 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)); } })); @@ -86,7 +90,10 @@ public int process(List 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 @@ -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"); @@ -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); } @@ -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) { @@ -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); } } @@ -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); @@ -241,10 +248,10 @@ private static void deleteTempFiles(Set 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"); } } } diff --git a/src/main/java/com/github/stickerifier/stickerify/logger/StructuredLogger.java b/src/main/java/com/github/stickerifier/stickerify/logger/StructuredLogger.java index 517a0106..3bef1bc1 100644 --- a/src/main/java/com/github/stickerifier/stickerify/logger/StructuredLogger.java +++ b/src/main/java/com/github/stickerifier/stickerify/logger/StructuredLogger.java @@ -8,15 +8,25 @@ public record StructuredLogger(Logger logger) { - public static final ScopedValue REQUEST_DETAILS = ScopedValue.newInstance(); - public static final ScopedValue MIME_TYPE = ScopedValue.newInstance(); + public static final ScopedValue REQUEST_DETAILS_VALUE = ScopedValue.newInstance(); + public static final ScopedValue FILE_ID_VALUE = ScopedValue.newInstance(); + public static final ScopedValue 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 @@ -24,11 +34,14 @@ public StructuredLogger(Class clazz) { 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; diff --git a/src/main/java/com/github/stickerifier/stickerify/media/MediaHelper.java b/src/main/java/com/github/stickerifier/stickerify/media/MediaHelper.java index 81d4c225..32ce6ceb 100644 --- a/src/main/java/com/github/stickerifier/stickerify/media/MediaHelper.java +++ b/src/main/java/com/github/stickerifier/stickerify/media/MediaHelper.java @@ -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; @@ -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)); } /** @@ -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); } } @@ -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 { @@ -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"); } @@ -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); @@ -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"); } } diff --git a/src/main/java/com/github/stickerifier/stickerify/telegram/Answer.java b/src/main/java/com/github/stickerifier/stickerify/telegram/Answer.java index 36eac391..90769756 100644 --- a/src/main/java/com/github/stickerifier/stickerify/telegram/Answer.java +++ b/src/main/java/com/github/stickerifier/stickerify/telegram/Answer.java @@ -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),