Skip to content
Open
8 changes: 8 additions & 0 deletions changelog/unreleased/SOLR-18091.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
title: Seperate the node/container level info from the core level info for the admin end points.
type: other # added, changed, fixed, deprecated, removed, dependency_update, security, other
authors:
- name: Eric Pugh
links:
- name: SOLR-18091
url: https://issues.apache.org/jira/browse/SOLR-18091
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
public class NodeSystemResponse extends SolrJerseyResponse {

@JsonProperty public String mode;
@JsonProperty public String host;
@JsonProperty public String zkHost;

@JsonProperty("solr_home")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.handler.admin;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.file.Path;
import java.util.Date;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.security.AuthorizationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This handler returns core level info. See {@link org.apache.solr.handler.admin.SystemInfoHandler}
*/
public class CoreInfoHandler extends RequestHandlerBase {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

@Override
public String getDescription() {
return "Get Core Info";
}

@Override
public Category getCategory() {
return Category.ADMIN;
}

@Override
public Name getPermissionName(AuthorizationContext request) {
return Name.CONFIG_READ_PERM;
}

@Override
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
rsp.setHttpCaching(false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this request handler need if (AdminHandlersProxy.maybeProxyToNodes(req, rsp, getCoreContainer(req))) { like SystemInfoHandler has? Is that soemthing every class needs?

SolrCore core = req.getCore();

rsp.add("core", getCoreInfo(core, req.getSchema()));
}

private SimpleOrderedMap<Object> getCoreInfo(SolrCore core, IndexSchema schema) {
SimpleOrderedMap<Object> info = new SimpleOrderedMap<>();

info.add("schema", schema != null ? schema.getSchemaName() : "no schema!");

// Now
info.add("now", new Date());

// Start Time
info.add("start", core.getStartTimeStamp());

// Solr Home
SimpleOrderedMap<Object> dirs = new SimpleOrderedMap<>();
dirs.add("cwd", Path.of(System.getProperty("user.dir")).toAbsolutePath().toString());
dirs.add("instance", core.getInstancePath().toString());
try {
dirs.add("data", core.getDirectoryFactory().normalize(core.getDataDir()));
} catch (IOException e) {
log.warn("Problem getting the normalized data directory path", e);
dirs.add("data", "N/A");
}
dirs.add("dirimpl", core.getDirectoryFactory().getClass().getName());
try {
dirs.add("index", core.getDirectoryFactory().normalize(core.getIndexDir()));
} catch (IOException e) {
log.warn("Problem getting the normalized index directory path", e);
dirs.add("index", "N/A");
}
info.add("directory", dirs);
return info;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.PlatformManagedObject;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
Expand Down Expand Up @@ -58,7 +56,6 @@
import org.apache.solr.metrics.GpuMetricsProvider;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.security.AuthorizationContext;
import org.apache.solr.security.AuthorizationPlugin;
import org.apache.solr.security.PKIAuthenticationPlugin;
Expand All @@ -69,9 +66,8 @@
import org.slf4j.LoggerFactory;

/**
* This handler returns system info
*
* @since solr 1.2
* This handler returns node/container level info. See {@link
* org.apache.solr.handler.admin.CoreInfoHandler}
*/
public class SystemInfoHandler extends RequestHandlerBase {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
Expand Down Expand Up @@ -218,13 +214,14 @@ private void initHostname() {
@Override
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
rsp.setHttpCaching(false);
SolrCore core = req.getCore();
if (AdminHandlersProxy.maybeProxyToNodes(req, rsp, getCoreContainer(req))) {
return; // Request was proxied to other node
}
if (core != null) rsp.add("core", getCoreInfo(core, req.getSchema()));
boolean solrCloudMode = getCoreContainer(req).isZooKeeperAware();
rsp.add("mode", solrCloudMode ? "solrcloud" : "std");

rsp.add("host", hostname);

if (solrCloudMode) {
rsp.add("zkHost", getCoreContainer(req).getZkController().getZkServerAddress());
}
Expand Down Expand Up @@ -262,42 +259,6 @@ private CoreContainer getCoreContainer(SolrQueryRequest req) {
return coreContainer == null ? cc : coreContainer;
}

/** Get system info */
private SimpleOrderedMap<Object> getCoreInfo(SolrCore core, IndexSchema schema) {
SimpleOrderedMap<Object> info = new SimpleOrderedMap<>();

info.add("schema", schema != null ? schema.getSchemaName() : "no schema!");

// Host
info.add("host", hostname);

// Now
info.add("now", new Date());

// Start Time
info.add("start", core.getStartTimeStamp());

// Solr Home
SimpleOrderedMap<Object> dirs = new SimpleOrderedMap<>();
dirs.add("cwd", Path.of(System.getProperty("user.dir")).toAbsolutePath().toString());
dirs.add("instance", core.getInstancePath().toString());
try {
dirs.add("data", core.getDirectoryFactory().normalize(core.getDataDir()));
} catch (IOException e) {
log.warn("Problem getting the normalized data directory path", e);
dirs.add("data", "N/A");
}
dirs.add("dirimpl", core.getDirectoryFactory().getClass().getName());
try {
dirs.add("index", core.getDirectoryFactory().normalize(core.getIndexDir()));
} catch (IOException e) {
log.warn("Problem getting the normalized index directory path", e);
dirs.add("index", "N/A");
}
info.add("directory", dirs);
return info;
}

/** Get system info */
public static SimpleOrderedMap<Object> getSystemInfo() {
SimpleOrderedMap<Object> info = new SimpleOrderedMap<>();
Expand Down Expand Up @@ -480,13 +441,13 @@ private static String humanReadableUnits(long bytes, DecimalFormat df) {
String newSizeAndUnits;

if (bytes / ONE_GB > 0) {
newSizeAndUnits = String.valueOf(df.format((float) bytes / ONE_GB)) + " GB";
newSizeAndUnits = df.format((float) bytes / ONE_GB) + " GB";
} else if (bytes / ONE_MB > 0) {
newSizeAndUnits = String.valueOf(df.format((float) bytes / ONE_MB)) + " MB";
newSizeAndUnits = df.format((float) bytes / ONE_MB) + " MB";
} else if (bytes / ONE_KB > 0) {
newSizeAndUnits = String.valueOf(df.format((float) bytes / ONE_KB)) + " KB";
newSizeAndUnits = df.format((float) bytes / ONE_KB) + " KB";
} else {
newSizeAndUnits = String.valueOf(bytes) + " bytes";
newSizeAndUnits = bytes + " bytes";
}

return newSizeAndUnits;
Expand Down
6 changes: 3 additions & 3 deletions solr/core/src/resources/ImplicitPlugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@
"class": "solr.LukeRequestHandler",
"useParams":"_ADMIN_LUKE"
},
"/admin/system": {
"class": "solr.SystemInfoHandler",
"useParams":"_ADMIN_SYSTEM"
"/admin/info": {
"class": "solr.CoreInfoHandler",
"useParams":"_ADMIN_CORE"
},
"/admin/file": {
"class": "solr.ShowFileRequestHandler",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.handler.admin;

import java.util.Date;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.junit.BeforeClass;
import org.junit.Test;

/** Test for {@link CoreInfoHandler} */
public class CoreInfoHandlerTest extends SolrTestCaseJ4 {

@BeforeClass
public static void beforeClass() throws Exception {
initCore("solrconfig.xml", "schema.xml");
}

@Test
public void testCoreInfoHandlerResponse() throws Exception {
CoreInfoHandler handler = new CoreInfoHandler();
SolrQueryRequest req = req();
SolrQueryResponse rsp = new SolrQueryResponse();

handler.handleRequestBody(req, rsp);

NamedList<Object> values = rsp.getValues();
assertNotNull("Response should not be null", values);

@SuppressWarnings("unchecked")
SimpleOrderedMap<Object> core = (SimpleOrderedMap<Object>) values.get("core");
assertNotNull("Core info should not be null", core);

// Verify schema name is present
String schema = (String) core.get("schema");
assertNotNull("Schema should not be null", schema);
assertEquals("test", schema);

// Verify 'now' date is present and reasonable
Date now = (Date) core.get("now");
assertNotNull("Now date should not be null", now);
Date currentTime = new Date();
long responseTime = now.getTime();
assertTrue(
"Response time should be close to current time",
Math.abs(currentTime.getTime() - responseTime) < 5000); // within 5 seconds

// Verify start time is present
Date start = (Date) core.get("start");
assertNotNull("Start time should not be null", start);
assertTrue("Start time should be before or equal to now", start.getTime() <= now.getTime());

// Verify directory info
@SuppressWarnings("unchecked")
SimpleOrderedMap<Object> directory = (SimpleOrderedMap<Object>) core.get("directory");
assertNotNull("Directory info should not be null", directory);

// Check all expected directory fields are present
assertNotNull("cwd should not be null", directory.get("cwd"));
assertNotNull("instance should not be null", directory.get("instance"));
assertNotNull("data should not be null", directory.get("data"));
assertNotNull("dirimpl should not be null", directory.get("dirimpl"));
assertNotNull("index should not be null", directory.get("index"));

assertFalse("HTTP caching should be disabled", rsp.isHttpCaching());

req.close();
}

@Test
public void testCoreInfoMatchesActualCore() throws Exception {
CoreInfoHandler handler = new CoreInfoHandler();

try (SolrQueryRequest req = req()) {
SolrCore core = req.getCore();
assertNotNull("Core should not be null", core);

SolrQueryResponse rsp = new SolrQueryResponse();
handler.handleRequestBody(req, rsp);

@SuppressWarnings("unchecked")
SimpleOrderedMap<Object> coreInfo = (SimpleOrderedMap<Object>) rsp.getValues().get("core");

// Verify the schema name matches what we expect
String schemaName = (String) coreInfo.get("schema");
assertEquals("Schema name should match", core.getLatestSchema().getSchemaName(), schemaName);

// Verify start time matches core's start time
Date startTime = (Date) coreInfo.get("start");
assertEquals(
"Start time should match core start time",
core.getStartTimeStamp().getTime(),
startTime.getTime());

// Verify instance path is correctly reported
@SuppressWarnings("unchecked")
SimpleOrderedMap<Object> directory = (SimpleOrderedMap<Object>) coreInfo.get("directory");
String instancePath = (String) directory.get("instance");
assertEquals("Instance path should match", core.getInstancePath().toString(), instancePath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* xref:property-substitution.adoc[]
* xref:core-discovery.adoc[]
* xref:configuring-solr-xml.adoc[]
* xref:system-info-handler.adoc[]
* xref:solr-properties.adoc[]

* xref:configuring-solrconfig-xml.adoc[]
Expand All @@ -31,6 +32,7 @@
** xref:caches-warming.adoc[]
** xref:requesthandlers-searchcomponents.adoc[]
** xref:implicit-requesthandlers.adoc[]
** xref:core-info-handler.adoc[]
** xref:realtime-get.adoc[]
** xref:initparams.adoc[]
** xref:requestdispatcher.adoc[]
Expand Down
Loading
Loading