SOLR-12860: MetricsHistoryHandler now uses PKI Auth for metrics collection in background thread

(cherry picked from commit f2c59db273)
This commit is contained in:
Jan Høydahl 2019-04-12 10:21:13 +02:00
parent 43f5e6170c
commit de432003a7
3 changed files with 102 additions and 1 deletions

View File

@ -142,6 +142,8 @@ Bug Fixes
* SOLR-13388: Fix FileExchangeRateProvider to be a public class, as it appears in schema.xml (Uwe Schindler)
* SOLR-12860: MetricsHistoryHandler now uses PKI Auth for metrics collection in background thread (janhoy, Lorenzo)
* SOLR-13339: Prevent recovery, fetching index being kicked off after SolrCores already closed (Cao Manh Dat)
* SOLR-13393: Fixed ZkClientClusterStateProvider to prevent risk of leaking ZkStateReader/threads when

View File

@ -75,6 +75,7 @@ import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.Base64;
import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.JavaBinCodec;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.Pair;
@ -110,7 +111,8 @@ import static java.util.stream.Collectors.toMap;
import static org.apache.solr.common.params.CommonParams.ID;
/**
*
* Collects metrics from all nodes in the system on a regular basis in a background thread.
* @since 7.4
*/
public class MetricsHistoryHandler extends RequestHandlerBase implements PermissionNameProvider, Closeable {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@ -360,6 +362,9 @@ public class MetricsHistoryHandler extends RequestHandlerBase implements Permiss
private void collectMetrics() {
log.debug("-- collectMetrics");
// Make sure we are a solr server thread, so we can use PKI auth, SOLR-12860
// This is a workaround since we could not instrument the ScheduledThreadPoolExecutor in ExecutorUtils
ExecutorUtil.setServerThreadFlag(true);
try {
checkSystemCollection();
} catch (Exception e) {
@ -369,6 +374,7 @@ public class MetricsHistoryHandler extends RequestHandlerBase implements Permiss
// get metrics
collectLocalReplicaMetrics();
collectGlobalMetrics();
ExecutorUtil.setServerThreadFlag(false);
}
private void collectLocalReplicaMetrics() {

View File

@ -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.cloud;
import java.util.List;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.cloud.SolrCloudManager;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.util.LogLevel;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.apache.solr.cloud.MetricsHistoryIntegrationTest.createHistoryRequest;
/**
* Tests that metrics history works even with Authentication enabled.
* We test that the scheduled calls to /admin/metrics use PKI auth and therefore succeeds
*/
@LogLevel("org.apache.solr.handler.admin=DEBUG,org.apache.solr.security=DEBUG")
public class MetricsHistoryWithAuthIntegrationTest extends SolrCloudTestCase {
private static SolrCloudManager cloudManager;
private static SolrClient solrClient;
private static final String SECURITY_JSON = "{\n" +
" 'authentication':{\n" +
" 'blockUnknown': false, \n" +
" 'class':'solr.BasicAuthPlugin',\n" +
" 'credentials':{'solr':'orwp2Ghgj39lmnrZOTm7Qtre1VqHFDfwAEzr0ApbN3Y= Ju5osoAqOX8iafhWpPP01E5P+sg8tK8tHON7rCYZRRw='}},\n" +
" 'authorization':{\n" +
" 'class':'solr.RuleBasedAuthorizationPlugin',\n" +
" 'user-role':{'solr':'admin'},\n" +
" 'permissions':[{'name':'metrics','collection': null,'path':'/admin/metrics','role':'admin'},\n" +
" {'name':'metrics','collection': null,'path':'/api/cluster/metrics','role':'admin'}]}}";
private static final CharSequence SOLR_XML_HISTORY_CONFIG =
"<history>\n" +
" <str name=\"collectPeriod\">2</str>\n" +
"</history>\n";
@BeforeClass
public static void setupCluster() throws Exception {
String solrXml = MiniSolrCloudCluster.DEFAULT_CLOUD_SOLR_XML.replace("<metrics>\n",
"<metrics>\n" + SOLR_XML_HISTORY_CONFIG);
// Spin up a cluster with a protected /admin/metrics handler, and a 2 seconds metrics collectPeriod
configureCluster(1)
.addConfig("conf", configset("cloud-minimal"))
.withSecurityJson(SECURITY_JSON)
.withSolrXml(solrXml)
.configure();
cloudManager = cluster.getJettySolrRunner(0).getCoreContainer().getZkController().getSolrCloudManager();
solrClient = cluster.getSolrClient();
// sleep a little to allow the handler to collect some metrics
cloudManager.getTimeSource().sleep(3000);
}
@AfterClass
public static void teardown() {
solrClient = null;
cloudManager = null;
}
@SuppressWarnings("unchecked")
@Test
public void testValuesAreCollected() throws Exception {
NamedList<Object> rsp = solrClient.request(createHistoryRequest(params(
CommonParams.ACTION, "get", CommonParams.NAME, "solr.jvm")));
assertNotNull(rsp);
// default format is LIST
NamedList<Object> data = (NamedList<Object>)rsp.findRecursive("metrics", "solr.jvm", "data");
assertNotNull(data);
// Has actual values. These will be 0.0 if metrics could not be collected
NamedList<Object> memEntry = (NamedList<Object>) ((NamedList<Object>) data.iterator().next().getValue()).get("values");
List<Double> heap = (List<Double>) memEntry.getAll("memory.heap.used").get(0);
assertTrue("Expected memory.heap.used > 0 in history", heap.get(240) > 0.01);
}
}