diff --git a/src/main/java/com/stacklens/JSONlogs/JsonLogLine.java b/src/main/java/com/stacklens/JSONlogs/JsonLogLine.java new file mode 100644 index 0000000..bcede7d --- /dev/null +++ b/src/main/java/com/stacklens/JSONlogs/JsonLogLine.java @@ -0,0 +1,26 @@ +package com.stacklens.JSONlogs; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class JsonLogLine { + private String timestamp; + private String level; + private String message; + + @JsonProperty("stack_trace") + private String stackTrace; + + // Getters and Setters + public String getTimestamp() { return timestamp; } + public void setTimestamp(String timestamp) { this.timestamp = timestamp; } + + public String getLevel() { return level; } + public void setLevel(String level) { this.level = level; } + + public String getMessage() { return message; } + public void setMessage(String message) { this.message = message; } + + public String getStackTrace() { return stackTrace; } + public void setStackTrace(String stackTrace) { this.stackTrace = stackTrace; } +} diff --git a/src/main/java/com/stacklens/JSONlogs/LogProcessor.java b/src/main/java/com/stacklens/JSONlogs/LogProcessor.java new file mode 100644 index 0000000..9079bb8 --- /dev/null +++ b/src/main/java/com/stacklens/JSONlogs/LogProcessor.java @@ -0,0 +1,39 @@ +package com.stacklens.JSONlogs; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class LogProcessor { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + public boolean isJsonLog(String logLine) { + if (logLine == null) return false; + String trimmed = logLine.trim(); + return trimmed.startsWith("{") && trimmed.endsWith("}"); + } + + public String parseToPlainText(String logLine) { + try { + JsonLogStructure jsonLog = objectMapper.readValue(logLine, JsonLogStructure.class); + StringBuilder plainText = new StringBuilder(); + + if (jsonLog.message() != null) { + plainText.append(jsonLog.message()); + } + if (jsonLog.stackTrace() != null && !jsonLog.stackTrace().isEmpty()) { + plainText.append("\n").append(jsonLog.stackTrace()); + } + return plainText.toString(); + } catch (Exception e) { + return logLine; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + record JsonLogStructure( + @JsonProperty("message") String message, + @JsonProperty("stack_trace") String stackTrace + ) {} +} \ No newline at end of file diff --git a/src/main/java/com/stacklens/analyzer/LogAnalyzer.java b/src/main/java/com/stacklens/analyzer/LogAnalyzer.java index 882a203..4a85ba1 100644 --- a/src/main/java/com/stacklens/analyzer/LogAnalyzer.java +++ b/src/main/java/com/stacklens/analyzer/LogAnalyzer.java @@ -1,8 +1,8 @@ package com.stacklens.analyzer; -import com.stacklens.classifier.IssueClassifier; +import com.stacklens.JSONlogs.LogProcessor; import com.stacklens.model.AnalysisResult; -import com.stacklens.model.Issue; +import com.stacklens.classifier.IssueClassifier; import java.io.BufferedReader; import java.io.IOException; @@ -15,38 +15,49 @@ import java.util.List; import java.util.stream.Collectors; -/** - * Reads log content (from file, stdin, or inline text) and coordinates analysis. - */ public class LogAnalyzer { private final IssueClassifier classifier; + private final LogProcessor logProcessor; public LogAnalyzer() { this.classifier = new IssueClassifier(); + this.logProcessor = new LogProcessor(); } LogAnalyzer(IssueClassifier classifier) { this.classifier = classifier; + this.logProcessor = new LogProcessor(); + } + + private List preprocessLines(List lines) { + return lines.stream() + .map(line -> { + if (logProcessor.isJsonLog(line)) { + return logProcessor.parseToPlainText(line); + } + return line; + }).flatMap(line -> Arrays.stream(line.split("\\r?\\n"))) + .collect(Collectors.toList()); } - /** Reads a log file from disk and analyzes its contents. */ public AnalysisResult analyzeFile(Path filePath) throws IOException { List lines = Files.readAllLines(filePath); - return new AnalysisResult(filePath.toString(), classifier.classify(lines)); + List processedLines = preprocessLines(lines); + return new AnalysisResult(filePath.toString(), classifier.classify(processedLines)); } - /** Reads from an InputStream (e.g. System.in when using stdin mode). */ public AnalysisResult analyzeStream(InputStream stream, String sourceLabel) throws IOException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { List lines = reader.lines().collect(Collectors.toList()); - return new AnalysisResult(sourceLabel, classifier.classify(lines)); + List processedLines = preprocessLines(lines); + return new AnalysisResult(sourceLabel, classifier.classify(processedLines)); } } - /** Analyzes a stack trace or log text pasted directly as a string. */ public AnalysisResult analyzeText(String text) { List lines = Arrays.asList(text.split("\\r?\\n")); - return new AnalysisResult("inline text", classifier.classify(lines)); + List processedLines = preprocessLines(lines); + return new AnalysisResult("inline text", classifier.classify(processedLines)); } -} +} \ No newline at end of file