-
-
Notifications
You must be signed in to change notification settings - Fork 765
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SLF4J logging support for Appium local service #1014
Add SLF4J logging support for Appium local service #1014
Conversation
Please adjust indentation in all source files |
*/ | ||
public void enableDefaultSlf4jLoggingOfOutputData() { | ||
addSlf4jLogMessageConsumer((logMessage, ctx) -> { | ||
if (ctx.level().equals(DEBUG)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mapping is not sufficient, since Appium server uses more levels, for example warn
and error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add the other levels as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I have never seen an actual log message on either warn
/error
level. Do you know if they follow same format as debug
? i.e. log message is prefixed with log level. Info
level tag is not added in log message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just able to trigger a WARN
message, but there is no log level indication in the log message it self. So will ignore warn
and error
levels for now.
Example
[Appium] Deprecated server args:
[Appium] --device-name => --default-capabilities '{"deviceName":"someName"}'
According to this, the above log message is at WARN
level:
https://github.com/appium/appium/blob/7a00b3f875991ba1d95359ed53a3eda47911f64b/lib/main.js#L44
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the actual level is added there if logging timestamp is enabled:
2018-08-31 08:17:13:813 - info: [debug] [JSONWP Proxy] Got response with status 200: {"value":{"using":"class chain","value":"**/XCUIElementTypeCollectionView[`name == 'add_participants.list'`]/XCUIElementTypeCell[$name == 'user_cell.name' AND value == 'qrj7pcz5'$]","description":"unable to find an element"},"sessionId":"A4FBAD14-ED57-46D4-9407-B91C76BCB415","status":7}
2018-08-31 08:17:13:814 - info: [debug] [MJSONWP] Matched JSONWP error code 7 to NoSuchElementError
2018-08-31 08:17:13:815 - error: [W3C] Encountered internal error running command: NoSuchElementError: An element could not be located on the page using the given search parameters.
2018-08-31 08:17:13:815 - error: [W3C] at XCUITestDriver.callee$0$0$ (/usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/lib/commands/find.js:130:13)
|
||
static Slf4jLogMessageContext parseSlf4jContextFromLogMessage(String logMessage) { | ||
Matcher m = LOGGER_CONTEXT_PATTERN.matcher(logMessage); | ||
String loggerName = "appium.service"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be in the constant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following you on this. What should be in the constant? Which constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private static final String LOGGER_NAME
* @return {@link Logger} instance associated with this context. | ||
* | ||
*/ | ||
public Logger logger() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
java getters usually start with get
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix that
thanks for comments! What should I adjust indentation to? it seems to match the rest of the code lines. |
@mykola-mokhnach Can you please give more context regarding you comment |
@mykola-mokhnach How many spaces should it be per indentation? |
4 spaces |
@mykola-mokhnach regarding loglevel Anything else that I have missed? |
*/ | ||
public void enableDefaultSlf4jLoggingOfOutputData() { | ||
addSlf4jLogMessageConsumer((logMessage, ctx) -> { | ||
if (ctx.getLevel().equals(DEBUG)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is anyway not very accurate, since this [debug]
prefix is also not always added to debug logs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mykola-mokhnach So what do you sugests instead? Should all be logged at INFO
level? As it is now log messages with [debug]
prefix is logged at DEBUG
level. That is better than nothing if you ask me.
}); | ||
} | ||
|
||
static Slf4jLogMessageContext parseSlf4jContextFromLogMessage(String logMessage) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
codacy does not like package-level visibility. Please add public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mykola-mokhnach There is a big difference between public and package private. Making it public will make it part of the public API, which is not desired in this case.
I don't think we should make an implementation detail public just because codacy says so, or?
* | ||
*/ | ||
public void addLogMessageConsumer(Consumer<String> consumer) { | ||
addOutPutStream(new OutputStream() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following this comment? addOutPutStream(...)
is the name of an already existing method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a typo in this word
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mykola-mokhnach
I'm still not following what this has to do with this PR?
As I said the addOutPutStream(...)
method is already existing. Changing its name would be a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then yes, it is better to keep it as is if it was there
assertLoggerContext(DEBUG, "appium.service.xcuitest", | ||
"[debug] [XCUITest] Xcode version set to 'x.y.z' "); | ||
assertLoggerContext(DEBUG, "appium.service.jsonwpproxy", | ||
"[debug] [JSONWP Proxy] Proxying [GET /status] to [GET http://localhost:18218/status] with no body"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you parse messages with timestamps like 2018-08-31 08:17:13:741 - info: [debug] [JSONWP Proxy] Matched '/element' to command name 'findElement'
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as mentioned in javadoc. this feature is not supported when --log-timestamp
is enabled.
from javadoc:
NOTE2: it is required that {@code --log-timestamp} server flag is {@code false}.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List<String> log = new ArrayList<>(); | ||
service = buildDefaultService(); | ||
service.clearOutPutStreams(); | ||
service.addLogMessageConsumer(log::add); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we also have a possibility to remove a consumer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Essentially a consumer in this case is an OutputStream (as added with addOutPutStream(...)
method). So consumers can be removed with the clearOutPutStreams()
method.
* BiConsumer block to be executed when a log message is | ||
* available. | ||
*/ | ||
public void addSlf4jLogMessageConsumer( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it useful to return self instance from such methods, so one can chain them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it is nice to return self
to chain method calls. But no other methods in this class does that, so I figured to follow same pattern as other methods. Would be strange if only this method returned self
.
I just realized these methods does not do a null check of given arguments. Will fix that.
|
Will this be merged? |
Change list
Add possibilty to enable server output data logging through SLF4J loggers. This allow server output data to be configured with your preferred logging frameworks (e.g. java.util.logging, logback, log4j).
Types of changes
Details
Normal use case:
By default log messages are:
INFO
level, unless log message is pre-fixed by[debug]
then logged atDEBUG
level.Example of log messages:
"[ADB] Cannot read version codes of "
is logged by logger:appium.service.adb
at levelINFO
"[debug] [XCUITest] Xcode version set to 'x.y.z' "
is logged by loggerappium.service.xcuitest
at levelDEBUG
More general purposes
These methods are provided for more general use cases: