From dad03a3415ec551a99afeda287f3d6d5fde456ed Mon Sep 17 00:00:00 2001 From: GiuseppeS Date: Mon, 18 Nov 2024 19:32:42 +0100 Subject: [PATCH] Implementata gestione nei thread dei log di build --- pom.xml | 6 +- .../plugins/sample/PBAutoBuildBuilder.java | 15 ++- .../sample/PBAutoBuildConsoleAnnotator.java | 124 +++++++++++++----- .../sample/PBAutoBuildConsoleParser.java | 92 ++++++++++++- 4 files changed, 190 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index 0027620..66aa993 100644 --- a/pom.xml +++ b/pom.xml @@ -32,14 +32,14 @@ - 1.0.4 + 1.0.7 -SNAPSHOT - 2.440.3 + 2.462.3 jenkinsci/${project.artifactId}-plugin - false + true diff --git a/src/main/java/io/jenkins/plugins/sample/PBAutoBuildBuilder.java b/src/main/java/io/jenkins/plugins/sample/PBAutoBuildBuilder.java index f792ce3..a34536c 100644 --- a/src/main/java/io/jenkins/plugins/sample/PBAutoBuildBuilder.java +++ b/src/main/java/io/jenkins/plugins/sample/PBAutoBuildBuilder.java @@ -16,6 +16,7 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.Arrays; +import java.util.Objects; public class PBAutoBuildBuilder extends Builder implements SimpleBuildStep { /** @@ -100,7 +101,7 @@ public class PBAutoBuildBuilder extends Builder implements SimpleBuildStep { @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - return runPBAutoBuild(build, build.getWorkspace(), launcher, listener); + return runPBAutoBuild(build, Objects.requireNonNull(build.getWorkspace()), launcher, listener); } @Override @@ -154,10 +155,10 @@ public class PBAutoBuildBuilder extends Builder implements SimpleBuildStep { if (!launcher.isUnix()) { - final int cpi = getCodePageIdentifier(build.getCharset()); - if (cpi != 0) - args.prepend("cmd.exe", "/C", "\"", "chcp", String.valueOf(cpi), "&&"); - else +// final int cpi = getCodePageIdentifier(build.getCharset()); +// if (cpi != 0) +// args.prepend("cmd.exe", "/C", "\"", "chcp", String.valueOf(cpi), "&&"); +// else args.prepend("cmd.exe", "/C", "\""); args.add("\"", "&&", "exit", "%%ERRORLEVEL%%"); } @@ -166,9 +167,9 @@ public class PBAutoBuildBuilder extends Builder implements SimpleBuildStep { listener.getLogger() .println(String.format("Executing the command %s from %s", args.toStringWithQuote(), workspace)); // Parser to find the number of Warnings/Errors - PBAutoBuildConsoleParser mbcp = new PBAutoBuildConsoleParser(listener.getLogger(), build.getCharset()); + PBAutoBuildConsoleParser mbcp = new PBAutoBuildConsoleParser(listener.getLogger(), build.getCharset(), false); PBAutoBuildConsoleAnnotator annotator = new PBAutoBuildConsoleAnnotator(listener.getLogger(), - build.getCharset(), false); + build.getCharset(), false, workspace.getRemote()); // Launch the pbautobuild utility int r = launcher.launch().cmds(args).envs(env).stdout(mbcp).stdout(annotator).pwd(workspace).join(); diff --git a/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleAnnotator.java b/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleAnnotator.java index 58f7866..699fbef 100644 --- a/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleAnnotator.java +++ b/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleAnnotator.java @@ -1,12 +1,15 @@ package io.jenkins.plugins.sample; import hudson.console.LineTransformationOutputStream; + +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.Arrays; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -14,6 +17,7 @@ public class PBAutoBuildConsoleAnnotator extends LineTransformationOutputStream private final OutputStream out; private final Charset charset; private final boolean verboseLogging; + private final String workspace; private final PBAutoBuildErrorNote errorNote = new PBAutoBuildErrorNote(); private final PBAutoBuildWarningNote warningNote = new PBAutoBuildWarningNote(); @@ -33,16 +37,24 @@ public class PBAutoBuildConsoleAnnotator extends LineTransformationOutputStream // Pattern per i file (solo nome, escludendo il percorso) private Pattern fileNamePattern = Pattern.compile("([^\\\\]+\\.\\w+)$"); + private Pattern timestampPattern = Pattern.compile("(^\\d{2}:\\d{2}:\\d{2})"); // Pattern per Stage1, Stage2 e Regenerating private Pattern stagePattern = Pattern.compile("(Normal|Stage1|Stage2|Regenerating) for ([a-zA-Z]:\\\\.*?\\\\([^\\\\]+\\.\\w+))"); + private final Queue queueLog = new ConcurrentLinkedQueue<>(); + private Thread consumerThread; + private boolean consumerThreadRunning; - public PBAutoBuildConsoleAnnotator(OutputStream out, Charset charset, boolean verboseLogging) { + + public PBAutoBuildConsoleAnnotator(OutputStream out, Charset charset, boolean verboseLogging, String workspace) { this.out = out; this.charset = charset; this.verboseLogging = verboseLogging; + this.workspace = workspace + File.separator; + + startQueueConsumer(); } public int getNumberOfWarnings() { @@ -55,28 +67,65 @@ public class PBAutoBuildConsoleAnnotator extends LineTransformationOutputStream @Override protected void eol(byte[] b, int len) throws IOException { - String line = charset.decode(ByteBuffer.wrap(b, 0, len)).toString(); + queueLog.add(b); + } + + @Override + public void close() throws IOException { + stopQueueConsumer(); + super.close(); + out.close(); + } + + private void startQueueConsumer() { + consumerThreadRunning = true; + consumerThread = new Thread(() -> { + while (consumerThreadRunning) { + if (!queueLog.isEmpty()) { + final byte[] item = queueLog.poll(); + + if (item != null) { + try { + processLine(item); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } else { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + }); + consumerThread.start(); + } + + private void processLine(byte[] b) throws IOException { + String line = charset.decode(ByteBuffer.wrap(b, 0, b.length)).toString(); byte[] bytes1 = line.getBytes(charset); - String lineUtf16 = StandardCharsets.UTF_16.decode(ByteBuffer.wrap(b, 0, len)).toString(); + String lineUtf16 = StandardCharsets.UTF_16.decode(ByteBuffer.wrap(b, 0, b.length)).toString(); boolean isUtf16 = true; - for(int i = 0; i < bytes1.length; i = i+2) { - if(bytes1[i] != 0) { + for (int i = 0; i < bytes1.length; i = i + 2) { + if (bytes1[i] != 0) { isUtf16 = false; break; } } - if(isUtf16) { + if (isUtf16) { line = lineUtf16; } - - // trim off CR/LF from the end line = trimEOL(line); + if (line.isEmpty()) return; + // Error messages handler Matcher m = PBAutoBuildErrorNote.PATTERN.matcher(line); if (m.matches()) { // Match the number of warnings @@ -91,39 +140,48 @@ public class PBAutoBuildConsoleAnnotator extends LineTransformationOutputStream this.numberOfWarnings++; } - if(verboseLogging) - out.write(b, 0, len); - else { + + if (verboseLogging) { + line += "\r\n"; + byte[] b1 = line.getBytes(charset); + out.write(b1, 0, b1.length); + } else { // Estrarre i dati - String version = extractData(line, versionPattern); - String runtimePath = extractData(line, runtimePattern); - String workPath = extractData(line, workPathPattern); - String project = extractData(line, projectPattern); - String filename = extractFileNames(line, fileNamePattern); - String stage = extractStages(line, stagePattern); +// String version = extractData(line, versionPattern); +// String runtimePath = extractData(line, runtimePattern); +// String workPath = extractData(line, workPathPattern); +// String project = extractData(line, projectPattern); + String timestamp = extractData(line, timestampPattern); +// String filename = extractFileNames(line, fileNamePattern); +// String stage = extractStages(line, stagePattern); - if(line.contains("[Normal]")) { - //if(line.contains("\\")) - // line = line.substring(line.lastIndexOf("\\")); + line = line.replace(workspace, "") + .replace("\t", " "); + + if (timestamp != null && !timestamp.isEmpty()) + line = line.replace(timestamp, "").trim(); + + + line += "\r\n"; + byte[] bytesToWrite = line.getBytes(charset); + out.write(bytesToWrite, 0, bytesToWrite.length); - byte[] bytesToWrite = line.getBytes(charset); - out.write(bytesToWrite, 0, bytesToWrite.length); - } } } - @Override - public void close() throws IOException { - super.close(); - out.close(); + // Metodo per fermare il thread di consumo + public void stopQueueConsumer() { + consumerThreadRunning = false; + synchronized (queueLog) { + queueLog.notify(); // Se il thread รจ in attesa, sveglialo + } } - private String extractData(String log, Pattern pattern) { Matcher matcher = pattern.matcher(log); - if (matcher.matches()) { - return matcher.group(1); + if (matcher.find()) { + return matcher.group(0); } return null; @@ -132,7 +190,7 @@ public class PBAutoBuildConsoleAnnotator extends LineTransformationOutputStream private String extractFileNames(String log, Pattern pattern) { Matcher matcher = pattern.matcher(log); if (matcher.find()) { - return matcher.group(1); // Nome del file senza percorso + return matcher.group(0); // Nome del file senza percorso } return null; @@ -141,7 +199,7 @@ public class PBAutoBuildConsoleAnnotator extends LineTransformationOutputStream private String extractStages(String log, Pattern pattern) { Matcher matcher = pattern.matcher(log); if (matcher.find()) { - return "[" + matcher.group(1) + "] " + matcher.group(3); // Stage (Stage1, Stage2, ecc.) + return "[" + matcher.group(0) + "] " + matcher.group(2); // Stage (Stage1, Stage2, ecc.) } return null; } diff --git a/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleParser.java b/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleParser.java index 1619768..9fc5ac1 100644 --- a/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleParser.java +++ b/src/main/java/io/jenkins/plugins/sample/PBAutoBuildConsoleParser.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -43,9 +44,32 @@ public class PBAutoBuildConsoleParser extends LineTransformationOutputStream { private int numberOfWarnings = -1; private int numberOfErrors = -1; - public PBAutoBuildConsoleParser(OutputStream out, Charset charset) { + private boolean verboseLogging = false; + + private final Pattern patternWarnings = Pattern.compile(".*\\d+\\sWarning\\(s\\).*"); + private final Pattern patternErrors = Pattern.compile(".*\\d+\\sError\\(s\\).*"); + + // Pattern per Versione e Runtime + private Pattern versionPattern = Pattern.compile("PBAutoBuild Version: ([\\d\\.]+)"); + private Pattern runtimePattern = Pattern.compile("Runtime Version: ([\\d\\.]+)"); + + // Pattern per Work Path + private Pattern workPathPattern = Pattern.compile("Work Path: (.+\\.exe)"); + + // Pattern per i progetti + private Pattern projectPattern = Pattern.compile("Deploying project ([a-zA-Z0-9_]+)"); + + // Pattern per i file (solo nome, escludendo il percorso) + private Pattern fileNamePattern = Pattern.compile("([^\\\\]+\\.\\w+)$"); + + // Pattern per Stage1, Stage2 e Regenerating + private Pattern stagePattern = Pattern.compile("(Normal|Stage1|Stage2|Regenerating) for ([a-zA-Z]:\\\\.*?\\\\([^\\\\]+\\.\\w+))"); + + + public PBAutoBuildConsoleParser(OutputStream out, Charset charset, boolean verboseLogging) { this.out = out; this.charset = charset; + this.verboseLogging = verboseLogging; } public int getNumberOfWarnings() { @@ -59,12 +83,26 @@ public class PBAutoBuildConsoleParser extends LineTransformationOutputStream { @Override protected void eol(byte[] b, int len) throws IOException { String line = charset.decode(ByteBuffer.wrap(b, 0, len)).toString(); + byte[] bytes1 = line.getBytes(charset); + + String lineUtf16 = StandardCharsets.UTF_16.decode(ByteBuffer.wrap(b, 0, len)).toString(); + + boolean isUtf16 = true; + for(int i = 0; i < bytes1.length; i = i+2) { + if(bytes1[i] != 0) { + isUtf16 = false; + break; + } + } + + if(isUtf16) { + line = lineUtf16; + } // trim off CR/LF from the end line = trimEOL(line); - Pattern patternWarnings = Pattern.compile(".*\\d+\\sWarning\\(s\\).*"); - Pattern patternErrors = Pattern.compile(".*\\d+\\sError\\(s\\).*"); + if(line.isEmpty()) return; Matcher mWarnings = patternWarnings.matcher(line); Matcher mErrors = patternErrors.matcher(line); @@ -86,7 +124,25 @@ public class PBAutoBuildConsoleParser extends LineTransformationOutputStream { } // Write to output - out.write(b, 0, len); + if(verboseLogging) + out.write(b, 0, len); + else { + // Estrarre i dati + String version = extractData(line, versionPattern); + String runtimePath = extractData(line, runtimePattern); + String workPath = extractData(line, workPathPattern); + String project = extractData(line, projectPattern); + String filename = extractFileNames(line, fileNamePattern); + String stage = extractStages(line, stagePattern); + + if(line.contains("[Normal]")) { + //if(line.contains("\\")) + // line = line.substring(line.lastIndexOf("\\")); + + byte[] bytesToWrite = line.getBytes(charset); + out.write(bytesToWrite, 0, bytesToWrite.length); + } + } } @Override @@ -94,4 +150,32 @@ public class PBAutoBuildConsoleParser extends LineTransformationOutputStream { super.close(); out.close(); } + + + + private String extractData(String log, Pattern pattern) { + Matcher matcher = pattern.matcher(log); + if (matcher.matches()) { + return matcher.group(1); + } + + return null; + } + + private String extractFileNames(String log, Pattern pattern) { + Matcher matcher = pattern.matcher(log); + if (matcher.find()) { + return matcher.group(1); // Nome del file senza percorso + } + + return null; + } + + private String extractStages(String log, Pattern pattern) { + Matcher matcher = pattern.matcher(log); + if (matcher.find()) { + return "[" + matcher.group(1) + "] " + matcher.group(3); // Stage (Stage1, Stage2, ecc.) + } + return null; + } } \ No newline at end of file