|
223 | 223 | import java.nio.channels.ClosedByInterruptException;
|
224 | 224 | import java.util.concurrent.ExecutionException;
|
225 | 225 | import java.util.logging.ConsoleHandler;
|
| 226 | +import java.util.logging.Formatter; |
226 | 227 | import java.util.logging.Handler;
|
227 | 228 | import jenkins.model.ParameterizedJobMixIn;
|
| 229 | +import jenkins.security.MasterToSlaveCallable; |
228 | 230 | import org.hamcrest.core.IsInstanceOf;
|
229 | 231 | import org.junit.rules.DisableOnDebug;
|
230 | 232 | import org.junit.rules.Timeout;
|
@@ -988,6 +990,53 @@ public void waitOnline(Slave s) throws Exception {
|
988 | 990 | }
|
989 | 991 | }
|
990 | 992 |
|
| 993 | + /** |
| 994 | + * Same as {@link #showAgentLogs(Slave, Map)} but taking a preconfigured list of loggers as a convenience. |
| 995 | + */ |
| 996 | + public void showAgentLogs(Slave s, LoggerRule loggerRule) throws Exception { |
| 997 | + showAgentLogs(s, loggerRule.getRecordedLevels()); |
| 998 | + } |
| 999 | + |
| 1000 | + /** |
| 1001 | + * Forward agent logs to standard error of the test process. |
| 1002 | + * Otherwise log messages would be sent only to {@link Computer#getLogText} etc., |
| 1003 | + * or discarded entirely (if below {@link Level#INFO}). |
| 1004 | + * @param s an <em>online</em> agent |
| 1005 | + * @param loggers {@link Logger#getName} tied to log level |
| 1006 | + */ |
| 1007 | + public void showAgentLogs(Slave s, Map<String, Level> loggers) throws Exception { |
| 1008 | + s.getChannel().call(new RemoteLogDumper(s.getNodeName(), loggers)); |
| 1009 | + } |
| 1010 | + |
| 1011 | + private static final class RemoteLogDumper extends MasterToSlaveCallable<Void, RuntimeException> { |
| 1012 | + private final String name; |
| 1013 | + private final Map<String, Level> loggers; |
| 1014 | + private final TaskListener stderr = StreamTaskListener.fromStderr(); |
| 1015 | + RemoteLogDumper(String name, Map<String, Level> loggers) { |
| 1016 | + this.name = name; |
| 1017 | + this.loggers = loggers; |
| 1018 | + } |
| 1019 | + @Override public Void call() throws RuntimeException { |
| 1020 | + Handler handler = new Handler() { |
| 1021 | + final Formatter formatter = new SupportLogFormatter(); |
| 1022 | + @Override public void publish(LogRecord record) { |
| 1023 | + if (isLoggable(record)) { |
| 1024 | + stderr.getLogger().print(formatter.format(record).replaceAll("(?m)^", "[" + name + "] ")); |
| 1025 | + } |
| 1026 | + } |
| 1027 | + @Override public void flush() {} |
| 1028 | + @Override public void close() throws SecurityException {} |
| 1029 | + }; |
| 1030 | + handler.setLevel(Level.ALL); |
| 1031 | + loggers.entrySet().forEach(e -> { |
| 1032 | + Logger logger = Logger.getLogger(e.getKey()); |
| 1033 | + logger.setLevel(e.getValue()); |
| 1034 | + logger.addHandler(handler); |
| 1035 | + }); |
| 1036 | + return null; |
| 1037 | + } |
| 1038 | + } |
| 1039 | + |
991 | 1040 | /**
|
992 | 1041 | * Blocks until the ENTER key is hit.
|
993 | 1042 | * This is useful during debugging a test so that one can inspect the state of Hudson through the web browser.
|
|
0 commit comments