-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-29775 Allow inspecting log levels in Master UI in read-only mode #7540
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
base: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Thank you for the fix @jinhyukify. Changes looks good to me, do you mind extending this class 'TestLogLevel' to cover missing readonly scenario, if any? |
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.
Pull request overview
This PR enables read-only inspection of log levels in the Master UI when hbase.master.ui.readonly is configured. Previously, the readonly check blocked all access to the LogLevel servlet; now it only blocks modification operations while allowing users to view current log levels.
- Moves the readonly configuration check from blocking all requests to only blocking modification requests (when the
levelparameter is present) - Relocates Configuration object retrieval to after parameter extraction to support conditional readonly enforcement
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (conf.getBoolean("hbase.master.ui.readonly", false)) { | ||
| sendError(response, HttpServletResponse.SC_FORBIDDEN, | ||
| "Modification of HBase via the UI is disallowed in configuration."); | ||
| return; | ||
| } |
Copilot
AI
Dec 15, 2025
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 readonly check at line 333 occurs after the response body has already been written (header.jsp included at line 310, FORMS written at line 316, and potentially more output at lines 326-330). Calling sendError() at this point will not work correctly because the HTTP response has already been committed. The status code cannot be changed after the response body has started being written, which will result in either an IllegalStateException or a malformed HTTP response.
To fix this issue, the readonly check should be moved earlier in the method, before any output is written to the response. One approach would be to check if level is not null and readonly mode is enabled right after retrieving the parameters (around line 320), but before writing any output beyond that point. Alternatively, the check could be conditional on whether we're about to write the forms or process the request.
|
🎊 +1 overall
This message was automatically generated. |
|
🎊 +1 overall
This message was automatically generated. |
| System.out.println(fetchGetLevelResponse()); | ||
| } | ||
|
|
||
| String fetchGetLevelResponse() throws Exception { | ||
| return fetchResponse(protocol + "://" + hostName + "/logLevel?log=" + className); |
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 previous implementation printed results only to standard output, making it hard to write tests. I refactored the code slightly to separate the logic.
| testSetLogLevel(Protocol.C_HTTP_S_HTTP, true, logName, "INFO"); | ||
| fail("Setting log level should be disallowed in readonly mode."); |
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 verifies log level updates in read-only mode.
| public void testGetLogLevelAllowedInReadonlyMode() throws Exception { | ||
| withMasterUIReadonly(() -> { | ||
| Log4jUtils.setLogLevel(logName, "DEBUG"); | ||
| testGetLogLevel(Protocol.C_HTTP_S_HTTP, true, logName, "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 verifies log level reads in read-only mode.
|
@NihalJain Thank you for checking this! The current code structure made it difficult to write tests, so I did a small refactoring and added test cases. |
| .collect(Collectors.joining("\n")); | ||
| } catch (IOException ioe) { | ||
| System.err.println("" + ioe); | ||
| return "" + ioe; |
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.
In the old logic, this will go to stderr, but now it will go to stdout? I'm not very familiar with this area, so I'm not sure whether this is a problem...
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.
Thanks for the review. Good catch.
One thing I wanted to mention is that the previous behavior already felt a bit inconsistent.
We were catching only IOException here and printing it to standard error, while other exceptions were simply propagated..
That special handling for IOException feels slightly odd to me. Since this is a CLI command, I am considering not catching IOException here at all and letting it propagate, the same way other exceptions do.
I understand that this could technically be a behavior change for users who rely on standard error, but printing only this specific exception to stderr also seems inconsistent from a CLI semantics point of view.
I would like to hear your thoughts on whether there is a strong reason to keep this special case.
Jira https://issues.apache.org/jira/browse/HBASE-29775
Please refer to this comment for testing details.