Skip to content

Commit 0cc96a1

Browse files
improve logging
1 parent befaad4 commit 0cc96a1

2 files changed

Lines changed: 83 additions & 16 deletions

File tree

README.markdown

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ The tunnel comes with various options:
4646
|---------|-------------|
4747
|-a,--auth <host:port:user:passwd>|Performs Basic Authentication for specific hosts.|
4848
|-b,--nobump|Do not perform SSL bumping.|
49-
|-d,--debug|Enables debug messages. Will output request/response headers.|
49+
|-d,--debug|Enables debug messages. Will output request/response headers. Alias for `--log-level debug`.|
5050
|-dns,--dns|Use a custom DNS server. For example: 8.8.8.8|
5151
|--doctor|Perform sanity/health checks to detect possible misconfiguration or problems.|
5252
|--extra-headers <JSON Map with Header Key and Value>|Inject extra headers in the requests the tunnel makes.|
@@ -56,6 +56,7 @@ The tunnel comes with various options:
5656
|-i,--tunnel-identifier <id>|Add an identifier to this tunnel connection. In case of multiple tunnels, specify this identifier in your desired capabilities to use this specific tunnel.|
5757
|-j,--localproxy <port>|The port to launch the local proxy on (default 8087).|
5858
|-l,--logfile <FILE>|Write logging to a file.|
59+
|--log-level <LEVEL>|Set log verbosity. One of: `error`, `warn`, `info` (default), `debug`, `trace`. Overrides `--debug` if both are given.|
5960
|--metrics-port <port>|Use the specified port to access metrics. Default port 8003|
6061
|-P,--se-port <PORT>|The local port your Selenium test should connect to. Default port is 4445|
6162
|-p,--hubport <HUBPORT>|Use this if you want to connect to port 80 on our hub instead of the default port 4444|

src/main/java/com/testingbot/tunnel/App.java

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.Map;
1919
import java.util.logging.ConsoleHandler;
2020
import java.util.logging.FileHandler;
21-
import java.util.logging.Handler;
2221
import java.util.logging.Level;
2322
import java.util.logging.Logger;
2423
import com.fasterxml.jackson.databind.JsonNode;
@@ -116,7 +115,11 @@ public static void main(String... args) throws Exception {
116115
final Options options = new Options();
117116

118117
options.addOption("h", "help", false, "Displays help text");
119-
options.addOption("d", "debug", false, "Enables debug messages");
118+
options.addOption("d", "debug", false, "Enables debug messages (alias for --log-level debug)");
119+
120+
Option logLevel = new Option(null, "log-level", true, "Set log verbosity. One of: error, warn, info (default), debug, trace. Overrides --debug if both are given.");
121+
logLevel.setArgName("LEVEL");
122+
options.addOption(logLevel);
120123

121124
Option readyfile = new Option("f", "readyfile", true, "This file will be touched when the tunnel is ready for usage");
122125
readyfile.setArgName("FILE");
@@ -205,28 +208,91 @@ public static void main(String... args) throws Exception {
205208
logger.addHandler(handler);
206209

207210
App app = new App();
208-
if (commandLine.hasOption("debug")) {
209-
System.setProperty("org.eclipse.jetty.LEVEL", "DEBUG");
211+
212+
String levelArg = commandLine.getOptionValue("log-level");
213+
if (levelArg == null && commandLine.hasOption("debug")) {
214+
levelArg = "debug";
215+
}
216+
if (levelArg == null) {
217+
levelArg = "info";
218+
}
219+
220+
Level julLevel;
221+
ch.qos.logback.classic.Level logbackLevel;
222+
String jettyLevel;
223+
switch (levelArg.toLowerCase(java.util.Locale.ROOT)) {
224+
case "error":
225+
julLevel = Level.SEVERE;
226+
logbackLevel = ch.qos.logback.classic.Level.ERROR;
227+
jettyLevel = "ERROR";
228+
break;
229+
case "warn":
230+
case "warning":
231+
julLevel = Level.WARNING;
232+
logbackLevel = ch.qos.logback.classic.Level.WARN;
233+
jettyLevel = "WARN";
234+
break;
235+
case "info":
236+
julLevel = Level.INFO;
237+
logbackLevel = ch.qos.logback.classic.Level.INFO;
238+
jettyLevel = "INFO";
239+
break;
240+
case "debug":
241+
julLevel = Level.ALL;
242+
logbackLevel = ch.qos.logback.classic.Level.DEBUG;
243+
jettyLevel = "DEBUG";
244+
break;
245+
case "trace":
246+
julLevel = Level.ALL;
247+
logbackLevel = ch.qos.logback.classic.Level.TRACE;
248+
jettyLevel = "TRACE";
249+
break;
250+
default:
251+
throw new ParseException("Invalid --log-level '" + levelArg + "'. Use one of: error, warn, info, debug, trace.");
252+
}
253+
254+
logger.setLevel(julLevel);
255+
System.setProperty("org.eclipse.jetty.LEVEL", jettyLevel);
256+
257+
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
258+
loggerContext.getLogger("ROOT").setLevel(logbackLevel);
259+
loggerContext.getLogger("org.apache.hc").setLevel(logbackLevel);
260+
261+
boolean debugLike = (logbackLevel.toInt() <= ch.qos.logback.classic.Level.DEBUG.toInt());
262+
if (debugLike) {
263+
loggerContext.getLogger("org.eclipse.jetty").setLevel(logbackLevel);
264+
loggerContext.getLogger("com.testingbot.tunnel.proxy").setLevel(logbackLevel);
210265
logger.log(Level.INFO, "Running in debug-mode");
211-
logger.setLevel(Level.ALL);
212266
app.setDebugMode(true);
213-
214-
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
215-
loggerContext.getLogger("ROOT").setLevel(ch.qos.logback.classic.Level.DEBUG);
216-
loggerContext.getLogger("org.apache.hc").setLevel(ch.qos.logback.classic.Level.DEBUG);
217-
} else {
218-
logger.setLevel(Level.INFO);
219267
}
220268

221269
if (commandLine.hasOption("logfile")) {
270+
String logfilePath = commandLine.getOptionValue("logfile");
222271
try {
223-
Handler handlerFile = new FileHandler(commandLine.getOptionValue("logfile"));
272+
FileHandler handlerFile = new FileHandler(logfilePath, true);
224273
handlerFile.setFormatter(new LogFormatter());
225274
handlerFile.setLevel(Level.ALL);
226-
Logger.getLogger(App.class.getName()).addHandler(handlerFile);
227-
Logger.getLogger(App.class.getName()).log(Level.INFO, "Logging to file {0}", commandLine.getOptionValue("logfile"));
275+
// Attach to App's logger (useParentHandlers=false above) AND to the JUL root
276+
// so messages from sibling loggers (HttpProxy, SSHTunnel, Doctor, ...) land in the file too.
277+
logger.addHandler(handlerFile);
278+
Logger.getLogger("").addHandler(handlerFile);
279+
280+
ch.qos.logback.classic.encoder.PatternLayoutEncoder encoder = new ch.qos.logback.classic.encoder.PatternLayoutEncoder();
281+
encoder.setContext(loggerContext);
282+
encoder.setPattern("%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n");
283+
encoder.start();
284+
ch.qos.logback.core.FileAppender<ch.qos.logback.classic.spi.ILoggingEvent> fileAppender = new ch.qos.logback.core.FileAppender<>();
285+
fileAppender.setContext(loggerContext);
286+
fileAppender.setName("FILE");
287+
fileAppender.setFile(logfilePath);
288+
fileAppender.setAppend(true);
289+
fileAppender.setEncoder(encoder);
290+
fileAppender.start();
291+
loggerContext.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME).addAppender(fileAppender);
292+
293+
logger.log(Level.INFO, "Logging to file {0}", logfilePath);
228294
} catch (IOException | SecurityException e) {
229-
System.err.println("Cannot write logfile to " + commandLine.getOptionValue("logfile") + ".\nMake sure the directory exists and that we have the proper rights to write to this directory.");
295+
System.err.println("Cannot write logfile to " + logfilePath + ".\nMake sure the directory exists and we have permission to write there.");
230296
}
231297
}
232298

0 commit comments

Comments
 (0)