-
Notifications
You must be signed in to change notification settings - Fork 808
SOLR-18113: Revamp ZookeeperInfoHandler #4124
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: main
Are you sure you want to change the base?
Conversation
Now I see why we would want request handlers to inject their own request writers ;-)
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
Revamps Solr’s /admin/zookeeper handler behavior to better support the Admin UI “Cloud -> Graph” view and adds initial SolrCloud tests around the endpoint.
Changes:
- Update the Admin UI Angular Zookeeper service to stop requesting the removed
/clusterstate.jsonpseudo-path. - Adjust
ZookeeperInfoHandlerto produce structured response data (rather than returning a rawContentStream) and tweak paging/graph behavior. - Register
wt=rawas a built-in response writer and add new SolrCloud tests for/admin/zookeeper.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| solr/webapp/web/js/angular/services.js | Align UI ZK calls with the handler’s updated graph/paging behavior (no /clusterstate.json path). |
| solr/core/src/test/org/apache/solr/handler/admin/ZookeeperInfoHandlerTest.java | Adds basic SolrCloud tests validating /admin/zookeeper responses for detail and graph views. |
| solr/core/src/java/org/apache/solr/response/ResponseWritersRegistry.java | Adds built-in raw response writer support for container-level handlers. |
| solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java | Switches from raw ContentStream responses to parsed/structured response values and adjusts graph pagination logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java
Outdated
Show resolved
Hide resolved
solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java
Show resolved
Hide resolved
| // Force JSON response and omit header for cleaner output | ||
| Map<String, String> map = Map.of(WT, "json", OMIT_HEADER, "true"); |
Copilot
AI
Feb 9, 2026
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 comment "allows any response writer (json, xml, etc.)" conflicts with the earlier wrapDefaults(new MapSolrParams(map), params) call, which forces wt=json because the forced params are the primary params. Either update the comment to reflect that JSON is enforced, or stop forcing wt if other writers are intended to work.
| // Force JSON response and omit header for cleaner output | |
| Map<String, String> map = Map.of(WT, "json", OMIT_HEADER, "true"); | |
| // Force omitting the response header for cleaner output; allow client to choose response writer | |
| Map<String, String> map = Map.of(OMIT_HEADER, "true"); |
…, but have the same .print() method
|
I created a large number of collections using this script. Note, it would fail around collection 60 or so! |
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
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * Handles the graph view request with paginated collections. | ||
| * | ||
| * @param params Request parameters including pagination settings | ||
| * @return JSON string representing paginated collection data |
Copilot
AI
Feb 9, 2026
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.
Javadoc mismatch: handleGraphViewRequest returns a ZkBasePrinter, but the @return description says it returns a JSON string. Please update the Javadoc to reflect the actual return type/behavior.
| * @return JSON string representing paginated collection data | |
| * @return a {@link ZkBasePrinter} that will render the graph view for the requested page of collections |
| * Handles the path view request for a specific ZooKeeper path. | ||
| * | ||
| * @param params Request parameters including the path to display | ||
| * @return JSON string representing the ZooKeeper path data |
Copilot
AI
Feb 9, 2026
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.
Javadoc mismatch: handlePathViewRequest returns a ZkBasePrinter, but the @return description says it returns a JSON string. Please update the Javadoc to reflect the actual return type/behavior.
| * @return JSON string representing the ZooKeeper path data | |
| * @return a ZkBasePrinter that writes the ZooKeeper path data |
| validateParameters(params); | ||
|
|
||
| // Determine request type and handle accordingly | ||
| boolean isGraphView = "graph".equals(params.get("view")); |
Copilot
AI
Feb 9, 2026
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.
handleRequestBody now treats any request with view=graph as a graph request and ignores PATH entirely. Previously, graph-mode pagination was only enabled for the legacy "/clusterstate.json" pseudo-path; other paths could still be viewed even if view=graph was present. If this is intentional, consider validating/rejecting incompatible params (e.g., view=graph with a non-empty PATH) or documenting the precedence to avoid surprising API consumers.
| boolean isGraphView = "graph".equals(params.get("view")); | |
| boolean isGraphView = "graph".equals(params.get("view")); | |
| String path = params.get(PATH); | |
| if (isGraphView | |
| && StringUtils.isNotEmpty(path) | |
| && !"/clusterstate.json".equals(path)) { | |
| throw new SolrException( | |
| ErrorCode.BAD_REQUEST, | |
| "Parameter combination not supported: view=graph cannot be used with PATH='" | |
| + path | |
| + "'. Use an empty PATH or '/clusterstate.json' with view=graph."); | |
| } |
solr/core/src/java/org/apache/solr/handler/admin/ZookeeperInfoHandler.java
Outdated
Show resolved
Hide resolved
| this.zkController = controller; | ||
| keeperAddr = controller.getZkServerAddress(); | ||
| zkClient = controller.getZkClient(); | ||
| this.detail = detail; | ||
| this.dump = dump; | ||
| this.keeperAddr = controller.getZkServerAddress(); | ||
| this.zkClient = controller.getZkClient(); |
Copilot
AI
Feb 9, 2026
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.
ZkBasePrinter dereferences the passed ZkController without a null check. CoreContainer registers this handler even when not ZooKeeper-aware, so /admin/zookeeper in standalone mode can trigger a NullPointerException here. Please guard against cores.getZkController()==null (e.g., throw a BAD_REQUEST/SERVICE_UNAVAILABLE with a clear message) or make ZkBasePrinter tolerate a null controller and emit an error response.
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 guy doesnt't make sense in standalone, so it's okay.
| // start with json.startObject() and end with json.endObject() | ||
| @SuppressWarnings("unchecked") | ||
| Map<String, Object> jsonMap = (Map<String, Object>) Utils.fromJSONString(jsonString); | ||
|
|
||
| try { | ||
| if (paginateCollections) { | ||
| // List collections and allow pagination, but no specific znode info like when looking at a | ||
| // normal ZK path | ||
| printer.printPaginatedCollections(); | ||
| } else { | ||
| printer.print(path); | ||
| } | ||
| } finally { | ||
| printer.close(); | ||
| for (Map.Entry<String, Object> entry : jsonMap.entrySet()) { |
Copilot
AI
Feb 9, 2026
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 implementation stringifies JSON in the printer and then immediately parses it back into a Map (Utils.fromJSONString) before writing the response. That round-trip adds CPU + heap overhead proportional to response size (potentially large for deep ZK paths). Consider building structured objects directly (Map/NamedList) and adding them to rsp, or keep streaming output, to avoid the stringify->parse overhead.
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.
Copilot is so right here. "Raw" was being used to avoid this very thing. Let's not serialize & decode needlessly!
Another way to avoid this is a potentially large refactor of ZkBasePrinter to instead either produce plain Maps & arrays & such that Solr will serialize (to either Json or Xml even). I think you/LLM will find that easiest to understand. Or embrace Solr's MapWriter that allows very efficient just-in-time streaming. See https://issues.apache.org/jira/browse/SOLR-17582 #2916 for an example of that.
…Handler.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
dsmiley
left a comment
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.
Whatever becomes of ZookeeperInfoHandler, I think we should continue to keep "raw" an option at the node level. ZIH was maybe a hacky case since it returns JSON.
| // start with json.startObject() and end with json.endObject() | ||
| @SuppressWarnings("unchecked") | ||
| Map<String, Object> jsonMap = (Map<String, Object>) Utils.fromJSONString(jsonString); | ||
|
|
||
| try { | ||
| if (paginateCollections) { | ||
| // List collections and allow pagination, but no specific znode info like when looking at a | ||
| // normal ZK path | ||
| printer.printPaginatedCollections(); | ||
| } else { | ||
| printer.print(path); | ||
| } | ||
| } finally { | ||
| printer.close(); | ||
| for (Map.Entry<String, Object> entry : jsonMap.entrySet()) { |
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.
Copilot is so right here. "Raw" was being used to avoid this very thing. Let's not serialize & decode needlessly!
Another way to avoid this is a potentially large refactor of ZkBasePrinter to instead either produce plain Maps & arrays & such that Solr will serialize (to either Json or Xml even). I think you/LLM will find that easiest to understand. Or embrace Solr's MapWriter that allows very efficient just-in-time streaming. See https://issues.apache.org/jira/browse/SOLR-17582 #2916 for an example of that.

https://issues.apache.org/jira/browse/SOLR-18113
Description
Bit of revamp, see the JIRA.
Solution
TBD
Tests
Adding more tests