Repository navigation
SOLR-12613: node picker for cross-node screens - #5110
Conversation
…d Cluster/Node sidebar. Signed-off-by: prithvi <prithvisivasankar@gmail.com>
4915123 to
fc0b096
Compare
Signed-off-by: prithvi <prithvisivasankar@gmail.com>
… tests. Signed-off-by: prithvi <prithvisivasankar@gmail.com>
|
First question: The "node selector" dropdown, I suppose will still be valid only for the current node, i.e. query, update, schema, segments etc etc? Users may believe that it also obeys the chosen node. Not sure how to deal with that. |
There was a problem hiding this comment.
🟡 Changes recommended
Persisted targets can display local data as remote, and remote Core Admin views can execute mutations against the wrong node.
6 open findings
Core Admin mutates the local node while displaying a remote core · New Premature false initialization bypasses asynchronous mode detection · New Node targeting depends on asynchronous live-node discovery · New Reloaded remote nodes trigger child requests against the local node · New Node selector lacks an accessible semantic label · New Missing browser coverage for node selection and session restoration · New
What changed in this PR
Adds cross-node targeting to the legacy Admin UI and supporting V2 node APIs.
Changes:
- Adds a persistent live-node picker and reorganizes the sidebar.
- Extends node-local APIs with
nodesproxy support. - Adds backend proxy integration tests and UI styling.
| File | Description |
|---|---|
solr/webapp/web/partials/logging-levels.html |
Adds cluster-wide logging notice. |
solr/webapp/web/partials/index.html |
Displays the selected node. |
solr/webapp/web/partials/cores.html |
Uses cloud-mode state consistently. |
solr/webapp/web/partials/cloud.html |
Adds node dashboard and Admin UI links. |
solr/webapp/web/js/angular/services.js |
Introduces persistent node-target state. |
solr/webapp/web/js/angular/controllers/threads.js |
Targets thread dumps by node. |
solr/webapp/web/js/angular/controllers/logging.js |
Targets log messages and adjusts level broadcasting. |
solr/webapp/web/js/angular/controllers/java-properties.js |
Targets Java properties by node. |
solr/webapp/web/js/angular/controllers/index.js |
Targets dashboard system information. |
solr/webapp/web/js/angular/controllers/cores.js |
Loads core status from selected nodes. |
solr/webapp/web/js/angular/controllers/collection-overview.js |
Guards missing collection data. |
solr/webapp/web/js/angular/controllers/cloud.js |
Connects node rows to target selection. |
solr/webapp/web/js/angular/app.js |
Integrates node state into navigation. |
solr/webapp/web/index.html |
Adds the node picker and reorganized menu. |
solr/webapp/web/css/angular/menu.css |
Styles the reorganized sidebar and selectors. |
solr/webapp/web/css/angular/logging.css |
Styles the logging notice. |
solr/webapp/web/css/angular/common.css |
Styles the selected-node badge. |
solr/webapp/web/css/angular/cloud.css |
Styles node Admin UI links. |
solr/core/src/test/org/apache/solr/handler/admin/ThreadDumpHandlerTest.java |
Adapts thread-dump tests. |
solr/core/src/test/org/apache/solr/handler/admin/api/NodeLoggingAPITest.java |
Adapts logging API tests. |
solr/core/src/test/org/apache/solr/handler/admin/api/NodeAdminProxySolrCloudTest.java |
Tests proxied node APIs. |
solr/core/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java |
Adapts the V1 thread handler. |
solr/core/src/java/org/apache/solr/handler/admin/LoggingHandler.java |
Adapts the V1 logging handler. |
solr/core/src/java/org/apache/solr/handler/admin/api/NodeThreadsAPI.java |
Adds thread-dump proxying. |
solr/core/src/java/org/apache/solr/handler/admin/api/NodeLogging.java |
Adds logging-read proxying. |
solr/core/src/java/org/apache/solr/handler/admin/api/GetNodeProperties.java |
Adds properties proxying. |
solr/core/src/java/org/apache/solr/handler/admin/api/CoreStatus.java |
Adds core-status proxying. |
solr/api/src/java/org/apache/solr/client/api/model/NodeThreadsResponse.java |
Supports keyed remote responses. |
solr/api/src/java/org/apache/solr/client/api/model/NodePropertiesResponse.java |
Supports keyed remote responses. |
solr/api/src/java/org/apache/solr/client/api/model/LoggingResponse.java |
Supports keyed remote responses. |
solr/api/src/java/org/apache/solr/client/api/model/CoreStatusResponse.java |
Supports keyed remote responses. |
solr/api/src/java/org/apache/solr/client/api/endpoint/NodeThreadsApi.java |
Adds the nodes parameter. |
solr/api/src/java/org/apache/solr/client/api/endpoint/NodePropertiesApi.java |
Adds the nodes parameter. |
solr/api/src/java/org/apache/solr/client/api/endpoint/NodeLoggingApis.java |
Adds logging nodes parameters. |
solr/api/src/java/org/apache/solr/client/api/endpoint/CoreApis.java |
Adds core-status node targeting. |
changelog/unreleased/PR#5110-admin-ui-node-picker.yml |
Documents the feature. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| CoresV2.getAllCoreStatus(NodeTarget.withNodes({}), function(error, data, response) { | ||
| $timeout(function() { | ||
| if (error) { ApiErrorHandler.handle(response); return; } | ||
| var payload = NodeTarget.unwrap(data, response) || {}; |
yeah.. picker is only for the Node screens. core menu already hides on a remote node, and i added a "Node screens only" hint :) |
| ng-options="node as nodeLabel(node) for node in liveNodes"></select> | ||
| </div> | ||
| <p id="node-selector-hint" ng-class="{remote: viewingRemoteNode}"> | ||
| {{ viewingRemoteNode ? 'Remote node (Node screens only)' : 'This node — Node screens only' }} |
There was a problem hiding this comment.
I'm not convinced with this either...any better messaging which would help hre? @janhoy
Signed-off-by: prithvi <prithvisivasankar@gmail.com>
2365a02 to
996861b
Compare
|
@dsmiley Do you feel strongly about this vs your approach in #5112 ? David's more generic solution would proxy individual requests rather than aggregate, and would require the Admin UI to send N individual requests to the What I like the most about the ServletFilter approach is that the response shape stays the same and is thus more true to REST / OpenAPI. I.e. AdminUI can use a generated V2 API class to talk to logging / threads / xxx endpoint and get the response as an object. Less special code in UI, and less special code in Solr. What I like with the current PR is that it is ready, mergable and re-uses the same mechanism already used in AdminUI. It could ship in 10.2 and a refactor to |
|
I feel strongly in favor of the generic approach for the reasons you stated. I think it's also less code to maintain in the long run once the former mechanism can be removed. I'm ready to pursue my draft PR #5112 further... I was seeking feedback overall. |
LoggingController's log-message-history screen already followed NodeTarget, but LoggingLevelController's listAllLoggersAndLevels call never did, even though the backend endpoint already accepts nodes= (added by this same PR). Picking a remote node had no effect on the Level tree, silently showing local data while every other node-scoped screen correctly switched. Also fixes isNodeScopedPage's page-name regex in app.js, which recognized 'logging' (the history screen) but not 'logging-levels' (the Level screen), so the header's selected-node badge never rendered there even once the data was correctly node-scoped. Adds testLoggingLevelsScreenFollowsSelectedNode to close the test gap.
Backend (reuse + altitude, confirmed by independent review agents): - Add NodeProxyingJerseyResponse, housing the remoteNodeData field and its @JsonAnyGetter/@JsonAnySetter pair that CoreStatusResponse, LoggingResponse, NodePropertiesResponse, and NodeThreadsResponse each carried as identical copies. They now extend it instead of SolrJerseyResponse directly (ListLevelsResponse/LogMessagesResponse get it for free via their existing LoggingResponse parent). - Add V2SolrRequestBasedProxy.proxyToNodes(CoreContainer, SolrRequest, NodeProxyingJerseyResponse), a generic static helper replacing five near-identical private proxy methods in CoreStatus, GetNodeProperties, NodeLogging (x2), and NodeThreadsAPI. Also drops CoreStatus's stray extra nodes-null/empty guard, which was inconsistent with the other four call sites and already redundant (proxyRequest() already no-ops via shouldProxy() when nodes is unset). Frontend: - services.js: NodeTarget.unwrap()'s data.remoteNodeData[...] fallback branch was dead - confirmed empirically (a live 2-node cluster's raw JSON response) that @JsonAnyGetter flattens remoteNodeData's entries to the top level, so a literal 'remoteNodeData' key never appears on the wire; the body[selectedNode] branch above it is what actually matches. - app.js: resetMenu() fetched core status eagerly, then a second time after listClusterNodes resolved the selected node in cloud mode, discarding the first result; the eager call is now skipped once isCloudEnabled is known true. onSelectedNodeChange() also fetched cores manually right before .reload(), which re-fetches them anyway via resetMenu() before anything renders. Verified with the existing test suites (no behavior change): backend NodeAdminProxySolrCloudTest, NodeLoggingAPITest, ThreadDumpHandlerTest; frontend AdminUiNodePickerTest, AdminUiCoreAdminStandaloneTest, plus a broader Selenium sweep (AdminUiDashboardTest, AdminUiCoreAdminScreenTest, AdminUiLoggingScreenTest, AdminUiLoggingStandaloneTest, AdminUiNodeScreensTest, AdminUiCollectionsScreenTest, AdminUiSmokeTest) since resetMenu/onSelectedNodeChange are shared by every page.
|
@iprithv can you review my two commits? |
|
nice... |
It's a race! Nothing in this UI is landing until 10.2, so really no hurry.. If #5112 stalls out, then we can evaluate merging htis. |
|
AI Review:
|
|
Wouldn't it be reasonable for Solr to configure CORS? Granted, it's a dev-list discussion... |
|
Solr does not necessarily know the public host name (proxy etc) that the admin is served from, whether it is http or https (could be behind an ingress or WAF), etc, so CORS is not fun. Proxying is an elegant solution to the design-flaw that we don’t have a separate BFF for our admin. |
Signed-off-by: prithvi <prithvisivasankar@gmail.com>
| The first set of links are for system-level information and configuration and provide access to xref:deployment-guide:configuring-logging.adoc#logging-screen[Logging Screen], xref:deployment-guide:collections-core-admin.adoc[], and xref:deployment-guide:jvm-settings.adoc#java-properties-screen[Java Properties Screen], among other things. | ||
| The first set of links is split into Cluster (SolrCloud) and Node sections. | ||
| On SolrCloud, a Node picker chooses which live node Dashboard, Logging, Java Properties, Thread Dump, and Cores show. | ||
| Those screens are served from the node hosting the UI and routed with the `X-Solr-targetNode` header. |
There was a problem hiding this comment.
i don't think we need to explain the X-Sorl bit.. users don't care.
|
|
||
| function isNodeScopedUrl(url) { | ||
| url = url || ''; | ||
| return /\/api\/node\/(system|threads|properties|logging\/messages)(?:\?|$)/.test(url) |
Signed-off-by: prithvi <prithvisivasankar@gmail.com>
Signed-off-by: prithvi <prithvisivasankar@gmail.com>
bf4b115 to
73b3095
Compare
dsmiley
left a comment
There was a problem hiding this comment.
I think this PR should purely be about the front-end, powered by the X-Solr-targetNode header. No changes to v2 API etc.
| "Fetch status info for all cores hosted on this node, or on other live nodes when 'nodes' is set.", | ||
| tags = "cores") | ||
| CoreStatusResponse getAllCoreStatus( | ||
| @QueryParam("indexInfo") Boolean indexInfo, @QueryParam("nodes") String nodes) |
There was a problem hiding this comment.
please revert "nodes" params from v2
There was a problem hiding this comment.
yeah makes sense. dropped. thanks!
There was a problem hiding this comment.
just to make sure I'm keeping up... With the new X-Solr-targetNode we no longer need or want the nodes param right? And it got added in this PR to make some of the plumbing work, but wiht the new header, we can now remove that plumbing, and that simplifies our V2 api as well...
There was a problem hiding this comment.
yes exactly. It becomes deprecated stuff we don't want to v2-enable.
There was a problem hiding this comment.
Great... I'll leave this open till friday and merge... or if I am bored and walking the dog and looking at approved PR's that just need a merge ;-)
Signed-off-by: prithvi <prithvisivasankar@gmail.com>
dsmiley
left a comment
There was a problem hiding this comment.
Approving because my concern was fully addressed. But I did not review what remains here! I leave that assessment to Eric/others. I loved the video Eric shared!
|
Thanks for this Prithvi; this is a very useful Admin UI feature! I'm glad I could provide the infrastructure below that made it possible -- good collaboration :-) |
(cherry picked from commit 0d40291)














https://issues.apache.org/jira/browse/SOLR-12613
HACKATHON :)
added a Node picker so Thread Dump, Java Properties, Logging, Cores, and Dashboard can target any live node via the existing nodes= proxy.
sidebar is split into Cluster and Node. Works in SolrCloud and stays out of the way in standalone.
NOTE: See the Video Walkthrough: https://share.descript.com/view/P2Fn8J8Zabh
SOLR-12613_.node.picker.for.cross-node.screens.mp4