Skip to content

SOLR-15823: Add nodes broadcast to the V2 logging levels GET endpoint - #5031

Open
nick-boss-tech wants to merge 6 commits into
apache:mainfrom
nick-boss-tech:solr-15823-levels-submit
Open

nick-boss-tech wants to merge 6 commits into
apache:mainfrom
nick-boss-tech:solr-15823-levels-submit

Conversation

@nick-boss-tech

@nick-boss-tech nick-boss-tech commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖 (posted on behalf of Nick Shanin)

https://issues.apache.org/jira/browse/SOLR-15823

What happens today

The companion PR for this ticket gave the V2 logging API a nodes parameter on PUT /node/logging/levels, so a level change can be broadcast to several nodes at once. The read side did not follow: GET /node/logging/levels takes no nodes parameter and always answers with the receiving node's own listing. That is a step back from V1, where GET /admin/info/logging?nodes=all aggregates every node's levels listing keyed by node name; from V2, an operator or tool that wants the cluster's levels has to call each node itself. This PR is the follow-up to the set-level PR, #5030: it is stacked on that PR's branch and is meant to land after it.

What this change does

GET /node/logging/levels accepts the same nodes parameter with the same semantics as the set-level PUT (NodeLoggingApis.java:34-43). nodes=all collects the listing from every live node; a comma-separated list collects it from those nodes. The receiving node does not also serve its own listing locally; it is covered only if the resolved set names it, in which case it calls itself over HTTP. Each node's full listing (watcher, levels, loggers) rides in the response under its node name, and requested nodes that did not respond are named under failedNodes. An unknown node name fails the request with a 400 before anything is sent, and nodes on a standalone (non-SolrCloud) node is a 400. Without nodes, the response is exactly what the endpoint returns today. Under the hood, the broadcast helper the set-level PR added is generalized to take any built request (NodeLogging.java:74-82, NodeLogging.java:122-166), so both endpoints share one copy of the standalone guard, the unknown-node pre-check, and the failedNodes computation. The V1 handler keeps passing null for nodes (LoggingHandler.java:91), so V1 requests serve locally exactly as before. The Admin UI needed one call-site fix for this PR: adding the optional nodes parameter changed the generated JS client's levels method from listAllLoggersAndLevels(callback) to listAllLoggersAndLevels(opts, callback), and the logging screen still passed its callback first, where it landed in the options slot and was dropped, so the screen's data never loaded. The screen now passes an empty options object (logging.js:129), and it keeps reading the local node, as it did under V1. The reference guide's logging page documents the parameter on the listing as well (configuring-logging.adoc:118-124).

Proof

Verified 2026-10-05 at head 6fa54c4 (the UI call-site fix on top of caf3dbf; the premise below is unchanged).

Premise, new tests against the companion branch's production code (head 100ad2e, where the GET ignores nodes): of the four new cases in NodeLoggingNodesSolrCloudTest (NodeLoggingNodesSolrCloudTest.java), the three substantive ones fail for the stated reason. The broadcast-all case finds no failedNodes and no per-node entries because the base answers with its local listing; the single-node case likewise; the unknown-node case gets a 200 response instead of the expected 400. The fourth case, which pins today's no-nodes response shape, passes there, as it should.

At this head: NodeLoggingNodesSolrCloudTest 8/8 (the four set-level cases plus the four levels-read cases above), NodeLoggingAPITest (NodeLoggingAPITest.java) 9/9 (including the unchanged local shape and the standalone guard for the GET), LoggingHandlerTest (LoggingHandlerTest.java) 1/1. Tidy, Error Prone compile for :solr:api and :solr:core, and :solr:api:check plus :solr:core:check -x test all pass. The Admin UI Selenium suites were rerun at this head on Windows: AdminUiLoggingScreenTest 3/3 and AdminUiLoggingStandaloneTest 1/1 pass (4 tests, no failures or errors), including the level tree load and the change-level flow in both modes, with no 400 or missing-request-body errors.

Limits

The other two logging endpoints do not honor nodes: GET /node/logging/messages (a node's buffered log history) and PUT /node/logging/messages/threshold. Both were scoped alongside this change and left out deliberately; we will open a follow-up ticket and PR for either on request.

Authorization for a broadcast read is checked exactly once, on the node that receives the request: this endpoint requires config-read permission there (NodeLogging.java:73-74). The fan-out then runs node to node through the container's internal client with PKI authentication (RemoteRequestProxy.java:135-137), the same path the set-level PR uses. On that path the proxied requests present the sending node's own identity rather than the original caller's, and a node that receives one does not re-authorize it (PKIAuthenticationPlugin.java:371-372): the receiving node runs no config-read check of its own for a listing the broadcast collects from it. A permission rule that is not cluster-wide is therefore effectively widened by the broadcast: a caller allowed config-read on the receiving node alone can read the level listing of every node the request names. The broadcast has not been tested on a cluster with authentication and authorization enabled.

A broadcast levels read inlines every node's full logger list, hundreds of entries per node, in a single response; there is no paging or summary form. The top-level levels and loggers fields stay empty under broadcast, the same shape the set-level PR poses for its per-node results.

Changelog: changelog/unreleased/SOLR-15823.yml (carried over from the companion PR; this PR adds no separate entry)

AI assistance

AI agents assisted with research, implementation, review, and drafting. Nick Shanin directed the work and takes responsibility for this contribution.

PUT /api/node/logging/levels now accepts a 'nodes' query parameter.
When present, NodeLogging fans the request out to the named nodes (or
every live node for nodes=all) through V2SolrRequestBasedProxy, the
same machinery GetNodeSystemInfo uses, and the response carries one
result per node plus the names of any requested nodes that did not
respond. Unknown node names are rejected before anything is sent, and
using 'nodes' outside SolrCloud mode is a 400 rather than an NPE. The
V1 handler now calls the endpoint method with a null nodes value so it
does not broadcast twice.
…oint

LoggingLevelController.setLevel now calls
LoggingV2.modifyLocalLogLevel unconditionally, passing nodes=all only
in SolrCloud mode, and the V1 Logging factory is deleted from
services.js.
@github-actions github-actions Bot added documentation Improvements or additions to documentation admin-ui tests cat:api labels Oct 5, 2026
Adding the optional 'nodes' parameter to the levels GET changed the
generated JS client signature from listAllLoggersAndLevels(callback)
to listAllLoggersAndLevels(opts, callback). The logging screen still
passed its callback first, so it landed in 'opts' and the response
handler never ran. Pass an empty options object, as the neighbouring
fetchLocalLogMessages call already does.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

admin-ui cat:api documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant