/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.action.admin;
import org.apache.lucene.util.Constants;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.cluster.node.hotthreads.NodeHotThreads;
import org.elasticsearch.action.admin.cluster.node.hotthreads.NodesHotThreadsRequestBuilder;
import org.elasticsearch.action.admin.cluster.node.hotthreads.NodesHotThreadsResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.test.ESIntegTestCase;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.lessThan;
public class HotThreadsIT extends ESIntegTestCase {
public void testHotThreadsDontFail() throws ExecutionException, InterruptedException {
/**
* This test just checks if nothing crashes or gets stuck etc.
*/
createIndex("test");
final int iters = scaledRandomIntBetween(2, 20);
final AtomicBoolean hasErrors = new AtomicBoolean(false);
for (int i = 0; i < iters; i++) {
final String type;
NodesHotThreadsRequestBuilder nodesHotThreadsRequestBuilder = client().admin().cluster().prepareNodesHotThreads();
if (randomBoolean()) {
TimeValue timeValue = new TimeValue(rarely() ? randomIntBetween(500, 5000) : randomIntBetween(20, 500));
nodesHotThreadsRequestBuilder.setInterval(timeValue);
}
if (randomBoolean()) {
nodesHotThreadsRequestBuilder.setThreads(rarely() ? randomIntBetween(500, 5000) : randomIntBetween(1, 500));
}
nodesHotThreadsRequestBuilder.setIgnoreIdleThreads(randomBoolean());
if (randomBoolean()) {
switch (randomIntBetween(0, 2)) {
case 2:
type = "cpu";
break;
case 1:
type = "wait";
break;
default:
type = "block";
break;
}
assertThat(type, notNullValue());
nodesHotThreadsRequestBuilder.setType(type);
} else {
type = null;
}
final CountDownLatch latch = new CountDownLatch(1);
nodesHotThreadsRequestBuilder.execute(new ActionListener<NodesHotThreadsResponse>() {
@Override
public void onResponse(NodesHotThreadsResponse nodeHotThreads) {
boolean success = false;
try {
assertThat(nodeHotThreads, notNullValue());
Map<String, NodeHotThreads> nodesMap = nodeHotThreads.getNodesMap();
assertThat(nodesMap.size(), equalTo(cluster().size()));
for (NodeHotThreads ht : nodeHotThreads.getNodes()) {
assertNotNull(ht.getHotThreads());
//logger.info(ht.getHotThreads());
}
success = true;
} finally {
if (!success) {
hasErrors.set(true);
}
latch.countDown();
}
}
@Override
public void onFailure(Exception e) {
logger.error("FAILED", e);
hasErrors.set(true);
latch.countDown();
fail();
}
});
indexRandom(true,
client().prepareIndex("test", "type1", "1").setSource("field1", "value1"),
client().prepareIndex("test", "type1", "2").setSource("field1", "value2"),
client().prepareIndex("test", "type1", "3").setSource("field1", "value3"));
ensureSearchable();
while(latch.getCount() > 0) {
assertHitCount(
client().prepareSearch()
.setQuery(matchAllQuery())
.setPostFilter(boolQuery().must(matchAllQuery()).mustNot(boolQuery().must(termQuery("field1", "value1")).must(termQuery("field1", "value2"))))
.get(),
3L);
}
latch.await();
assertThat(hasErrors.get(), is(false));
}
}
public void testIgnoreIdleThreads() throws ExecutionException, InterruptedException {
assumeTrue("no support for hot_threads on FreeBSD", Constants.FREE_BSD == false);
// First time, don't ignore idle threads:
NodesHotThreadsRequestBuilder builder = client().admin().cluster().prepareNodesHotThreads();
builder.setIgnoreIdleThreads(false);
builder.setThreads(Integer.MAX_VALUE);
NodesHotThreadsResponse response = builder.execute().get();
int totSizeAll = 0;
for (NodeHotThreads node : response.getNodesMap().values()) {
totSizeAll += node.getHotThreads().length();
}
// Second time, do ignore idle threads:
builder = client().admin().cluster().prepareNodesHotThreads();
builder.setThreads(Integer.MAX_VALUE);
// Make sure default is true:
assertEquals(true, builder.request().ignoreIdleThreads());
response = builder.execute().get();
int totSizeIgnoreIdle = 0;
for (NodeHotThreads node : response.getNodesMap().values()) {
totSizeIgnoreIdle += node.getHotThreads().length();
}
// The filtered stacks should be smaller than unfiltered ones:
assertThat(totSizeIgnoreIdle, lessThan(totSizeAll));
}
public void testTimestampAndParams() throws ExecutionException, InterruptedException {
NodesHotThreadsResponse response = client().admin().cluster().prepareNodesHotThreads().execute().get();
if (Constants.FREE_BSD) {
for (NodeHotThreads node : response.getNodesMap().values()) {
String result = node.getHotThreads();
assertTrue(result.indexOf("hot_threads is not supported") != -1);
}
} else {
for (NodeHotThreads node : response.getNodesMap().values()) {
String result = node.getHotThreads();
assertTrue(result.indexOf("Hot threads at") != -1);
assertTrue(result.indexOf("interval=500ms") != -1);
assertTrue(result.indexOf("busiestThreads=3") != -1);
assertTrue(result.indexOf("ignoreIdleThreads=true") != -1);
}
}
}
}