parent
774622abfb
commit
cfd8bddde4
|
@ -23,9 +23,6 @@ import org.elasticsearch.common.logging.ESLogger;
|
|||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
import org.elasticsearch.jmx.ManagedGroupName;
|
||||
|
||||
import static org.elasticsearch.index.IndexServiceManagement.buildIndexGroupName;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -77,9 +74,4 @@ public abstract class AbstractIndexComponent implements IndexComponent {
|
|||
public String nodeName() {
|
||||
return indexSettings.get("name", "");
|
||||
}
|
||||
|
||||
@ManagedGroupName
|
||||
private String managementGroupName() {
|
||||
return buildIndexGroupName(index);
|
||||
}
|
||||
}
|
|
@ -23,7 +23,6 @@ import org.elasticsearch.common.inject.AbstractModule;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.service.IndexService;
|
||||
import org.elasticsearch.index.service.InternalIndexService;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -39,8 +38,5 @@ public class IndexModule extends AbstractModule {
|
|||
@Override
|
||||
protected void configure() {
|
||||
bind(IndexService.class).to(InternalIndexService.class).asEagerSingleton();
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
bind(IndexServiceManagement.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.index;
|
||||
|
||||
import org.elasticsearch.common.component.CloseableComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.service.IndexService;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
import org.elasticsearch.jmx.MBean;
|
||||
import org.elasticsearch.jmx.ManagedAttribute;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@MBean(objectName = "", description = "")
|
||||
public class IndexServiceManagement extends AbstractIndexComponent implements CloseableComponent {
|
||||
|
||||
public static String buildIndexGroupName(Index index) {
|
||||
return "service=indices,index=" + index.name();
|
||||
}
|
||||
|
||||
private final JmxService jmxService;
|
||||
|
||||
private final IndexService indexService;
|
||||
|
||||
@Inject
|
||||
public IndexServiceManagement(Index index, @IndexSettings Settings indexSettings, JmxService jmxService, IndexService indexService) {
|
||||
super(index, indexSettings);
|
||||
this.jmxService = jmxService;
|
||||
this.indexService = indexService;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
jmxService.unregisterGroup(buildIndexGroupName(indexService.index()));
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Index Name")
|
||||
public String getIndex() {
|
||||
return indexService.index().name();
|
||||
}
|
||||
}
|
|
@ -55,7 +55,6 @@ import org.elasticsearch.index.search.stats.ShardSearchModule;
|
|||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
import org.elasticsearch.index.settings.IndexSettingsService;
|
||||
import org.elasticsearch.index.shard.IndexShardCreationException;
|
||||
import org.elasticsearch.index.shard.IndexShardManagement;
|
||||
import org.elasticsearch.index.shard.IndexShardModule;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.index.shard.service.IndexShard;
|
||||
|
@ -398,11 +397,6 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
|
|||
// ignore
|
||||
}
|
||||
|
||||
// close shard actions
|
||||
if (indexShard != null) {
|
||||
shardInjector.getInstance(IndexShardManagement.class).close();
|
||||
}
|
||||
|
||||
// this logic is tricky, we want to close the engine so we rollback the changes done to it
|
||||
// and close the shard so no operations are allowed to it
|
||||
if (indexShard != null) {
|
||||
|
|
|
@ -23,9 +23,6 @@ import org.elasticsearch.common.logging.ESLogger;
|
|||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
import org.elasticsearch.jmx.ManagedGroupName;
|
||||
|
||||
import static org.elasticsearch.index.shard.IndexShardManagement.buildShardGroupName;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -69,9 +66,4 @@ public abstract class AbstractIndexShardComponent implements IndexShardComponent
|
|||
public String nodeName() {
|
||||
return indexSettings.get("name", "");
|
||||
}
|
||||
|
||||
@ManagedGroupName
|
||||
public String managementGroupName() {
|
||||
return buildShardGroupName(shardId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.index.shard;
|
||||
|
||||
import org.elasticsearch.common.component.CloseableComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.index.engine.Engine;
|
||||
import org.elasticsearch.index.settings.IndexSettings;
|
||||
import org.elasticsearch.index.shard.service.IndexShard;
|
||||
import org.elasticsearch.index.store.Store;
|
||||
import org.elasticsearch.index.translog.Translog;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
import org.elasticsearch.jmx.MBean;
|
||||
import org.elasticsearch.jmx.ManagedAttribute;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.index.IndexServiceManagement.buildIndexGroupName;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@MBean(objectName = "", description = "")
|
||||
public class IndexShardManagement extends AbstractIndexShardComponent implements CloseableComponent {
|
||||
|
||||
public static String buildShardGroupName(ShardId shardId) {
|
||||
return buildIndexGroupName(shardId.index()) + ",subService=shards,shard=" + shardId.id();
|
||||
}
|
||||
|
||||
private final JmxService jmxService;
|
||||
|
||||
private final IndexShard indexShard;
|
||||
|
||||
private final Store store;
|
||||
|
||||
private final Translog translog;
|
||||
|
||||
@Inject
|
||||
public IndexShardManagement(ShardId shardId, @IndexSettings Settings indexSettings, JmxService jmxService, IndexShard indexShard,
|
||||
Store store, Translog translog) {
|
||||
super(shardId, indexSettings);
|
||||
this.jmxService = jmxService;
|
||||
this.indexShard = indexShard;
|
||||
this.store = store;
|
||||
this.translog = translog;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
jmxService.unregisterGroup(buildShardGroupName(indexShard.shardId()));
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Index Name")
|
||||
public String getIndex() {
|
||||
return indexShard.shardId().index().name();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Shard Id")
|
||||
public int getShardId() {
|
||||
return indexShard.shardId().id();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Storage Size")
|
||||
public String getStoreSize() {
|
||||
try {
|
||||
return store.estimateSize().toString();
|
||||
} catch (IOException e) {
|
||||
return "NA";
|
||||
}
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "The current transaction log id")
|
||||
public long getTranslogId() {
|
||||
return translog.currentId();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Number of transaction log operations")
|
||||
public long getTranslogNumberOfOperations() {
|
||||
return translog.estimatedNumberOfOperations();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Estimated size in memory the transaction log takes")
|
||||
public String getTranslogSize() {
|
||||
return new ByteSizeValue(translog.memorySizeInBytes()).toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "The state of the shard")
|
||||
public String getState() {
|
||||
return indexShard.state().toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Primary")
|
||||
public boolean isPrimary() {
|
||||
return indexShard.routingEntry().primary();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "The state of the shard as perceived by the cluster")
|
||||
public String getRoutingState() {
|
||||
return indexShard.routingEntry().state().toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "The number of documents in the index")
|
||||
public int getNumDocs() {
|
||||
Engine.Searcher searcher = indexShard.searcher();
|
||||
try {
|
||||
return searcher.reader().numDocs();
|
||||
} finally {
|
||||
searcher.release();
|
||||
}
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "The total number of documents in the index (including deleted ones)")
|
||||
public int getMaxDoc() {
|
||||
Engine.Searcher searcher = indexShard.searcher();
|
||||
try {
|
||||
return searcher.reader().maxDoc();
|
||||
} finally {
|
||||
searcher.release();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,6 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.index.shard.service.IndexShard;
|
||||
import org.elasticsearch.index.shard.service.InternalIndexShard;
|
||||
import org.elasticsearch.index.warmer.ShardIndexWarmerService;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -44,9 +43,6 @@ public class IndexShardModule extends AbstractModule {
|
|||
protected void configure() {
|
||||
bind(ShardId.class).toInstance(shardId);
|
||||
bind(IndexShard.class).to(InternalIndexShard.class).asEagerSingleton();
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
bind(IndexShardManagement.class).asEagerSingleton();
|
||||
}
|
||||
bind(ShardIndexWarmerService.class).asEagerSingleton();
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.index.store;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.index.shard.AbstractIndexShardComponent;
|
||||
import org.elasticsearch.jmx.MBean;
|
||||
import org.elasticsearch.jmx.ManagedAttribute;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@MBean(objectName = "shardType=store", description = "The storage of the index shard")
|
||||
public class StoreManagement extends AbstractIndexShardComponent {
|
||||
|
||||
private final Store store;
|
||||
|
||||
@Inject
|
||||
public StoreManagement(Store store) {
|
||||
super(store.shardId(), store.indexSettings());
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Size in bytes")
|
||||
public long getSizeInBytes() {
|
||||
try {
|
||||
return store.estimateSize().bytes();
|
||||
} catch (IOException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Size")
|
||||
public String getSize() {
|
||||
try {
|
||||
return store.estimateSize().toString();
|
||||
} catch (IOException e) {
|
||||
return "NA";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,6 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.index.store.distributor.Distributor;
|
||||
import org.elasticsearch.index.store.distributor.LeastUsedDistributor;
|
||||
import org.elasticsearch.index.store.distributor.RandomWeightedDistributor;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -50,9 +49,6 @@ public class StoreModule extends AbstractModule {
|
|||
protected void configure() {
|
||||
bind(DirectoryService.class).to(indexStore.shardDirectory()).asEagerSingleton();
|
||||
bind(Store.class).asEagerSingleton();
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
bind(StoreManagement.class).asEagerSingleton();
|
||||
}
|
||||
if (distributor == null) {
|
||||
distributor = loadDistributor(settings);
|
||||
}
|
||||
|
|
|
@ -353,7 +353,6 @@ public class InternalIndicesService extends AbstractLifecycleComponent<IndicesSe
|
|||
indexInjector.getInstance(IndexFieldDataService.class).clear();
|
||||
indexInjector.getInstance(AnalysisService.class).close();
|
||||
indexInjector.getInstance(IndexEngine.class).close();
|
||||
indexInjector.getInstance(IndexServiceManagement.class).close();
|
||||
|
||||
indexInjector.getInstance(IndexGateway.class).close(delete);
|
||||
indexInjector.getInstance(MapperService.class).close();
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
/**
|
||||
* Simple based class for JMX related services with {@link #doConfigure()} only being called if
|
||||
* jmx is enabled.
|
||||
*/
|
||||
public abstract class AbstractJmxModule extends AbstractModule {
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
protected AbstractJmxModule(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
doConfigure();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doConfigure();
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterStateListener;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.jmx.action.GetJmxServiceUrlAction;
|
||||
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static java.util.concurrent.Executors.newSingleThreadExecutor;
|
||||
import static org.elasticsearch.common.util.concurrent.EsExecutors.daemonThreadFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
// TODO Disabled for now. Can be used to mbean proxy other nodes in the cluster from within the same console. Need the jmxruntime_optional jars though..,
|
||||
public class JmxClusterService extends AbstractComponent {
|
||||
|
||||
private final ClusterService clusterService;
|
||||
|
||||
private final JmxService jmxService;
|
||||
|
||||
private final GetJmxServiceUrlAction getJmxServiceUrlAction;
|
||||
|
||||
private final ExecutorService clusterNodesJmxUpdater;
|
||||
|
||||
public JmxClusterService(Settings settings, ClusterService clusterService, JmxService jmxService, final GetJmxServiceUrlAction getJmxServiceUrlAction) {
|
||||
super(settings);
|
||||
this.clusterService = clusterService;
|
||||
this.jmxService = jmxService;
|
||||
this.getJmxServiceUrlAction = getJmxServiceUrlAction;
|
||||
|
||||
this.clusterNodesJmxUpdater = newSingleThreadExecutor(daemonThreadFactory(settings, "jmxService#updateTask"));
|
||||
|
||||
if (jmxService.publishUrl() != null) {
|
||||
clusterService.add(new JmxClusterEventListener());
|
||||
for (final DiscoveryNode node : clusterService.state().nodes()) {
|
||||
clusterNodesJmxUpdater.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String nodeServiceUrl = getJmxServiceUrlAction.obtainPublishUrl(node);
|
||||
registerNode(node, nodeServiceUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (clusterNodesJmxUpdater != null) {
|
||||
clusterNodesJmxUpdater.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerNode(DiscoveryNode node, String nodeServiceUrl) {
|
||||
try {
|
||||
JMXServiceURL jmxServiceURL = new JMXServiceURL(nodeServiceUrl);
|
||||
JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, null);
|
||||
|
||||
MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();
|
||||
|
||||
// for (ObjectName objectName : connection.queryNames(null, null)) {
|
||||
// try {
|
||||
// MBeanProxy mBeanProxy = new MBeanProxy(remoteName, connection);
|
||||
// } catch (InstanceAlreadyExistsException e) {
|
||||
// // ignore
|
||||
// } catch (Exception e) {
|
||||
// logger.warn("Failed to register proxy mbean", e);
|
||||
// }
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to register node [" + node + "] with serviceUrl [" + nodeServiceUrl + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
private class JmxClusterEventListener implements ClusterStateListener {
|
||||
@Override
|
||||
public void clusterChanged(ClusterChangedEvent event) {
|
||||
if (!event.nodesChanged()) {
|
||||
return;
|
||||
}
|
||||
for (final DiscoveryNode node : event.nodesDelta().addedNodes()) {
|
||||
clusterNodesJmxUpdater.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String nodeServiceUrl = getJmxServiceUrlAction.obtainPublishUrl(node);
|
||||
registerNode(node, nodeServiceUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmxConnectorCreationException extends JmxException {
|
||||
|
||||
public JmxConnectorCreationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JmxConnectorCreationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import org.elasticsearch.ElasticSearchException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmxException extends ElasticSearchException {
|
||||
|
||||
public JmxException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JmxException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.TypeLiteral;
|
||||
import org.elasticsearch.common.inject.matcher.Matchers;
|
||||
import org.elasticsearch.common.inject.spi.InjectionListener;
|
||||
import org.elasticsearch.common.inject.spi.TypeEncounter;
|
||||
import org.elasticsearch.common.inject.spi.TypeListener;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.jmx.action.GetJmxServiceUrlAction;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmxModule extends AbstractModule {
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
public JmxModule(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
JmxService jmxService = new JmxService(Loggers.getLogger(JmxService.class, settings.get("name")), settings);
|
||||
bind(JmxService.class).toInstance(jmxService);
|
||||
bind(GetJmxServiceUrlAction.class).asEagerSingleton();
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
bindListener(Matchers.any(), new JmxExporterTypeListener(jmxService));
|
||||
}
|
||||
}
|
||||
|
||||
private static class JmxExporterTypeListener implements TypeListener {
|
||||
|
||||
private final JmxService jmxService;
|
||||
|
||||
private JmxExporterTypeListener(JmxService jmxService) {
|
||||
this.jmxService = jmxService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) {
|
||||
Class<? super I> type = typeLiteral.getRawType();
|
||||
if (type.isAnnotationPresent(MBean.class)) {
|
||||
typeEncounter.register(new JmxExporterInjectionListener<I>(jmxService));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class JmxExporterInjectionListener<I> implements InjectionListener<I> {
|
||||
|
||||
private final JmxService jmxService;
|
||||
|
||||
private JmxExporterInjectionListener(JmxService jmxService) {
|
||||
this.jmxService = jmxService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterInjection(I instance) {
|
||||
jmxService.registerMBean(instance);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmxRegistrationException extends JmxException {
|
||||
|
||||
public JmxRegistrationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JmxRegistrationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -1,248 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.network.NetworkService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.PortsRange;
|
||||
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmxService {
|
||||
|
||||
public static class SettingsConstants {
|
||||
|
||||
public static final String EXPORT = "jmx.export";
|
||||
public static final String CREATE_CONNECTOR = "jmx.create_connector";
|
||||
}
|
||||
|
||||
public static boolean shouldExport(Settings settings) {
|
||||
return settings.getAsBoolean(SettingsConstants.CREATE_CONNECTOR, false) || settings.getAsBoolean(SettingsConstants.EXPORT, false);
|
||||
}
|
||||
|
||||
// we use {jmx.port} without prefix of $ since we don't want it to be resolved as a setting property
|
||||
|
||||
public static final String JMXRMI_URI_PATTERN = "service:jmx:rmi:///jndi/rmi://:{jmx.port}/jmxrmi";
|
||||
|
||||
public static final String JMXRMI_PUBLISH_URI_PATTERN = "service:jmx:rmi:///jndi/rmi://{jmx.host}:{jmx.port}/jmxrmi";
|
||||
|
||||
private final ESLogger logger;
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
private final String jmxDomain;
|
||||
|
||||
private String serviceUrl;
|
||||
|
||||
private String publishUrl;
|
||||
|
||||
private final MBeanServer mBeanServer;
|
||||
|
||||
private JMXConnectorServer connectorServer;
|
||||
|
||||
private final CopyOnWriteArrayList<ResourceDMBean> constructionMBeans = new CopyOnWriteArrayList<ResourceDMBean>();
|
||||
|
||||
private final CopyOnWriteArrayList<ResourceDMBean> registeredMBeans = new CopyOnWriteArrayList<ResourceDMBean>();
|
||||
|
||||
private String nodeDescription;
|
||||
|
||||
private volatile boolean started = false;
|
||||
|
||||
public JmxService(ESLogger logger, final Settings settings) {
|
||||
this.logger = logger;
|
||||
this.settings = settings;
|
||||
|
||||
this.jmxDomain = settings.get("jmx.domain", "org.elasticsearch");
|
||||
|
||||
this.mBeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
}
|
||||
|
||||
public String serviceUrl() {
|
||||
return this.serviceUrl;
|
||||
}
|
||||
|
||||
public String publishUrl() {
|
||||
return this.publishUrl;
|
||||
}
|
||||
|
||||
public void connectAndRegister(String nodeDescription, final NetworkService networkService) {
|
||||
if (started) {
|
||||
return;
|
||||
}
|
||||
started = true;
|
||||
this.nodeDescription = nodeDescription;
|
||||
if (settings.getAsBoolean(SettingsConstants.CREATE_CONNECTOR, false)) {
|
||||
// we are going to create the connector, set the GC interval to a large value
|
||||
try {
|
||||
if (System.getProperty("sun.rmi.dgc.client.gcInterval") == null)
|
||||
System.setProperty("sun.rmi.dgc.client.gcInterval", "36000000");
|
||||
if (System.getProperty("sun.rmi.dgc.server.gcInterval") == null)
|
||||
System.setProperty("sun.rmi.dgc.server.gcInterval", "36000000");
|
||||
} catch (Exception secExc) {
|
||||
logger.warn("Failed to set sun.rmi.dgc.xxx system properties", secExc);
|
||||
}
|
||||
|
||||
final String port = settings.get("jmx.port", "9400-9500");
|
||||
|
||||
PortsRange portsRange = new PortsRange(port);
|
||||
final AtomicReference<Exception> lastException = new AtomicReference<Exception>();
|
||||
boolean success = portsRange.iterate(new PortsRange.PortCallback() {
|
||||
@Override
|
||||
public boolean onPortNumber(int portNumber) {
|
||||
try {
|
||||
LocateRegistry.createRegistry(portNumber);
|
||||
serviceUrl = settings.get("jmx.service_url", JMXRMI_URI_PATTERN).replace("{jmx.port}", Integer.toString(portNumber));
|
||||
// Create the JMX service URL.
|
||||
JMXServiceURL url = new JMXServiceURL(serviceUrl);
|
||||
// Create the connector server now.
|
||||
connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, settings.getAsMap(), mBeanServer);
|
||||
connectorServer.start();
|
||||
|
||||
// create the publish url
|
||||
String publishHost = networkService.resolvePublishHostAddress(settings.get("jmx.publish_host")).getHostAddress();
|
||||
publishUrl = settings.get("jmx.publish_url", JMXRMI_PUBLISH_URI_PATTERN).replace("{jmx.port}", Integer.toString(portNumber)).replace("{jmx.host}", publishHost);
|
||||
} catch (Exception e) {
|
||||
lastException.set(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!success) {
|
||||
throw new JmxConnectorCreationException("Failed to bind to [" + port + "]", lastException.get());
|
||||
}
|
||||
logger.info("bound_address {{}}, publish_address {{}}", serviceUrl, publishUrl);
|
||||
}
|
||||
|
||||
for (ResourceDMBean resource : constructionMBeans) {
|
||||
register(resource);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerMBean(Object instance) {
|
||||
ResourceDMBean resourceDMBean = new ResourceDMBean(instance, logger);
|
||||
if (!resourceDMBean.isManagedResource()) {
|
||||
return;
|
||||
}
|
||||
if (!started) {
|
||||
constructionMBeans.add(resourceDMBean);
|
||||
return;
|
||||
}
|
||||
register(resourceDMBean);
|
||||
}
|
||||
|
||||
public void unregisterGroup(String groupName) {
|
||||
for (ResourceDMBean resource : registeredMBeans) {
|
||||
if (!groupName.equals(resource.getGroupName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
registeredMBeans.remove(resource);
|
||||
|
||||
String resourceName = resource.getFullObjectName();
|
||||
try {
|
||||
ObjectName objectName = new ObjectName(getObjectName(resourceName));
|
||||
if (mBeanServer.isRegistered(objectName)) {
|
||||
mBeanServer.unregisterMBean(objectName);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Unregistered " + objectName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to unregister " + resource.getFullObjectName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
if (!started) {
|
||||
return;
|
||||
}
|
||||
started = false;
|
||||
// unregister mbeans
|
||||
for (ResourceDMBean resource : registeredMBeans) {
|
||||
String resourceName = resource.getFullObjectName();
|
||||
try {
|
||||
ObjectName objectName = new ObjectName(getObjectName(resourceName));
|
||||
if (mBeanServer.isRegistered(objectName)) {
|
||||
mBeanServer.unregisterMBean(objectName);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Unregistered " + objectName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to unregister " + resource.getFullObjectName());
|
||||
}
|
||||
}
|
||||
if (connectorServer != null) {
|
||||
try {
|
||||
connectorServer.stop();
|
||||
} catch (IOException e) {
|
||||
logger.debug("Failed to close connector", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void register(ResourceDMBean resourceDMBean) throws JmxRegistrationException {
|
||||
try {
|
||||
String resourceName = resourceDMBean.getFullObjectName();
|
||||
ObjectName objectName = new ObjectName(getObjectName(resourceName));
|
||||
if (!mBeanServer.isRegistered(objectName)) {
|
||||
try {
|
||||
mBeanServer.registerMBean(resourceDMBean, objectName);
|
||||
registeredMBeans.add(resourceDMBean);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registered " + resourceDMBean + " under " + objectName);
|
||||
}
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
//this might happen if multiple instances are trying to concurrently register same objectName
|
||||
logger.debug("Could not register object with name:" + objectName + "(" + e.getMessage() + ")");
|
||||
}
|
||||
} else {
|
||||
logger.debug("Could not register object with name: " + objectName + ", already registered");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Could not register object with name: " + resourceDMBean.getFullObjectName() + "(" + e.getMessage() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private String getObjectName(String resourceName) {
|
||||
return getObjectName(jmxDomain, resourceName);
|
||||
}
|
||||
|
||||
private String getObjectName(String jmxDomain, String resourceName) {
|
||||
return jmxDomain + ":" + resourceName;
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
public @interface MBean {
|
||||
String description() default "";
|
||||
|
||||
String objectName() default "";
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD})
|
||||
public @interface ManagedAttribute {
|
||||
String description() default "";
|
||||
|
||||
boolean writable() default false;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
public @interface ManagedGroupName {
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
public @interface ManagedOperation {
|
||||
String description() default "";
|
||||
}
|
|
@ -1,570 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.Classes;
|
||||
import org.elasticsearch.common.Preconditions;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
|
||||
import javax.management.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.elasticsearch.common.collect.MapBuilder.newMapBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ResourceDMBean implements DynamicMBean {
|
||||
private static final Class<?>[] primitives = {int.class, byte.class, short.class, long.class,
|
||||
float.class, double.class, boolean.class, char.class};
|
||||
|
||||
private final ESLogger logger;
|
||||
|
||||
private final Object obj;
|
||||
|
||||
private final String objectName;
|
||||
|
||||
private final String groupName;
|
||||
|
||||
private final String fullObjectName;
|
||||
|
||||
private final String description;
|
||||
|
||||
private final MBeanAttributeInfo[] attributesInfo;
|
||||
|
||||
private final MBeanOperationInfo[] operationsInfo;
|
||||
|
||||
private final MBeanInfo mBeanInfo;
|
||||
|
||||
private final ImmutableMap<String, AttributeEntry> attributes;
|
||||
|
||||
private final ImmutableList<MBeanOperationInfo> operations;
|
||||
|
||||
public ResourceDMBean(Object instance, ESLogger logger) {
|
||||
Preconditions.checkNotNull(instance, "Cannot make an MBean wrapper for null instance");
|
||||
this.obj = instance;
|
||||
this.logger = logger;
|
||||
|
||||
MapBuilder<String, AttributeEntry> attributesBuilder = newMapBuilder();
|
||||
List<MBeanOperationInfo> operationsBuilder = new ArrayList<MBeanOperationInfo>();
|
||||
|
||||
MBean mBean = obj.getClass().getAnnotation(MBean.class);
|
||||
|
||||
this.groupName = findGroupName();
|
||||
|
||||
if (mBean != null && Strings.hasLength(mBean.objectName())) {
|
||||
objectName = mBean.objectName();
|
||||
} else {
|
||||
if (Strings.hasLength(groupName)) {
|
||||
// we have something in the group object name, don't put anything in the object name
|
||||
objectName = "";
|
||||
} else {
|
||||
objectName = obj.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(groupName);
|
||||
if (Strings.hasLength(groupName) && Strings.hasLength(objectName)) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(objectName);
|
||||
this.fullObjectName = sb.toString();
|
||||
|
||||
this.description = findDescription();
|
||||
findFields(attributesBuilder);
|
||||
findMethods(attributesBuilder, operationsBuilder);
|
||||
|
||||
this.attributes = attributesBuilder.immutableMap();
|
||||
this.operations = ImmutableList.copyOf(operationsBuilder);
|
||||
|
||||
attributesInfo = new MBeanAttributeInfo[attributes.size()];
|
||||
int i = 0;
|
||||
|
||||
MBeanAttributeInfo info;
|
||||
for (AttributeEntry entry : attributes.values()) {
|
||||
info = entry.getInfo();
|
||||
attributesInfo[i++] = info;
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.trace("Attribute " + info.getName() + "[r=" + info.isReadable() + ",w="
|
||||
+ info.isWritable() + ",is=" + info.isIs() + ",type=" + info.getType() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
operationsInfo = new MBeanOperationInfo[operations.size()];
|
||||
operations.toArray(operationsInfo);
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (operations.size() > 0)
|
||||
logger.trace("Operations are:");
|
||||
for (MBeanOperationInfo op : operationsInfo) {
|
||||
logger.trace("Operation " + op.getReturnType() + " " + op.getName());
|
||||
}
|
||||
}
|
||||
|
||||
this.mBeanInfo = new MBeanInfo(getObject().getClass().getCanonicalName(), description, attributesInfo, null, operationsInfo, null);
|
||||
}
|
||||
|
||||
public MBeanInfo getMBeanInfo() {
|
||||
return mBeanInfo;
|
||||
}
|
||||
|
||||
public synchronized Object getAttribute(String name) throws AttributeNotFoundException {
|
||||
if (name == null || name.length() == 0)
|
||||
throw new NullPointerException("Invalid attribute requested " + name);
|
||||
|
||||
Attribute attr = getNamedAttribute(name);
|
||||
if (attr == null) {
|
||||
throw new AttributeNotFoundException("Unknown attribute '" + name
|
||||
+ "'. Known attributes names are: " + attributes.keySet());
|
||||
}
|
||||
return attr.getValue();
|
||||
}
|
||||
|
||||
public synchronized void setAttribute(Attribute attribute) {
|
||||
if (attribute == null || attribute.getName() == null)
|
||||
throw new NullPointerException("Invalid attribute requested " + attribute);
|
||||
|
||||
setNamedAttribute(attribute);
|
||||
}
|
||||
|
||||
public synchronized AttributeList getAttributes(String[] names) {
|
||||
AttributeList al = new AttributeList();
|
||||
for (String name : names) {
|
||||
Attribute attr = getNamedAttribute(name);
|
||||
if (attr != null) {
|
||||
al.add(attr);
|
||||
} else {
|
||||
logger.warn("Did not find attribute " + name);
|
||||
}
|
||||
}
|
||||
return al;
|
||||
}
|
||||
|
||||
public synchronized AttributeList setAttributes(AttributeList list) {
|
||||
AttributeList results = new AttributeList();
|
||||
for (Object aList : list) {
|
||||
Attribute attr = (Attribute) aList;
|
||||
|
||||
if (setNamedAttribute(attr)) {
|
||||
results.add(attr);
|
||||
} else {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Failed to update attribute name " + attr.getName() + " with value "
|
||||
+ attr.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public Object invoke(String name, Object[] args, String[] sig) throws MBeanException,
|
||||
ReflectionException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Invoke method called on " + name);
|
||||
}
|
||||
|
||||
MBeanOperationInfo opInfo = null;
|
||||
for (MBeanOperationInfo op : operationsInfo) {
|
||||
if (op.getName().equals(name)) {
|
||||
opInfo = op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (opInfo == null) {
|
||||
final String msg = "Operation " + name + " not in ModelMBeanInfo";
|
||||
throw new MBeanException(new ServiceNotFoundException(msg), msg);
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?>[] classes = new Class[sig.length];
|
||||
for (int i = 0; i < classes.length; i++) {
|
||||
classes[i] = getClassForName(sig[i]);
|
||||
}
|
||||
Method method = getObject().getClass().getMethod(name, classes);
|
||||
return method.invoke(getObject(), args);
|
||||
} catch (Exception e) {
|
||||
throw new MBeanException(e);
|
||||
}
|
||||
}
|
||||
|
||||
Object getObject() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
private Class<?> getClassForName(String name) throws ClassNotFoundException {
|
||||
try {
|
||||
return Classes.getDefaultClassLoader().loadClass(name);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
// Could be a primitive - let's check
|
||||
for (Class<?> primitive : primitives) {
|
||||
if (name.equals(primitive.getName())) {
|
||||
return primitive;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ClassNotFoundException("Class " + name + " cannot be found");
|
||||
}
|
||||
|
||||
private String findGroupName() {
|
||||
Class objClass = getObject().getClass();
|
||||
while (objClass != Object.class) {
|
||||
Method[] methods = objClass.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
if (method.isAnnotationPresent(ManagedGroupName.class)) {
|
||||
try {
|
||||
method.setAccessible(true);
|
||||
return (String) method.invoke(getObject());
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to get group name for [" + getObject() + "]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
objClass = objClass.getSuperclass();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String findDescription() {
|
||||
MBean mbean = getObject().getClass().getAnnotation(MBean.class);
|
||||
if (mbean != null && mbean.description() != null && mbean.description().trim().length() > 0) {
|
||||
return mbean.description();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void findMethods(MapBuilder<String, AttributeEntry> attributesBuilder, List<MBeanOperationInfo> ops) {
|
||||
// find all methods but don't include methods from Object class
|
||||
List<Method> methods = new ArrayList<Method>(Arrays.asList(getObject().getClass().getMethods()));
|
||||
List<Method> objectMethods = new ArrayList<Method>(Arrays.asList(Object.class.getMethods()));
|
||||
methods.removeAll(objectMethods);
|
||||
|
||||
for (Method method : methods) {
|
||||
// does method have @ManagedAttribute annotation?
|
||||
ManagedAttribute attr = method.getAnnotation(ManagedAttribute.class);
|
||||
if (attr != null) {
|
||||
String methodName = method.getName();
|
||||
if (!methodName.startsWith("get") && !methodName.startsWith("set") && !methodName.startsWith("is")) {
|
||||
if (logger.isWarnEnabled())
|
||||
logger.warn("method name " + methodName
|
||||
+ " doesn't start with \"get\", \"set\", or \"is\""
|
||||
+ ", but is annotated with @ManagedAttribute: will be ignored");
|
||||
} else {
|
||||
MBeanAttributeInfo info;
|
||||
String attributeName = null;
|
||||
boolean writeAttribute = false;
|
||||
if (isSetMethod(method)) { // setter
|
||||
attributeName = methodName.substring(3);
|
||||
info = new MBeanAttributeInfo(attributeName, method.getParameterTypes()[0]
|
||||
.getCanonicalName(), attr.description(), true, true, false);
|
||||
writeAttribute = true;
|
||||
} else { // getter
|
||||
if (method.getParameterTypes().length == 0
|
||||
&& method.getReturnType() != java.lang.Void.TYPE) {
|
||||
boolean hasSetter = attributesBuilder.containsKey(attributeName);
|
||||
// we found is method
|
||||
if (methodName.startsWith("is")) {
|
||||
attributeName = methodName.substring(2);
|
||||
info = new MBeanAttributeInfo(attributeName, method.getReturnType()
|
||||
.getCanonicalName(), attr.description(), true, hasSetter, true);
|
||||
} else {
|
||||
// this has to be get
|
||||
attributeName = methodName.substring(3);
|
||||
info = new MBeanAttributeInfo(attributeName, method.getReturnType()
|
||||
.getCanonicalName(), attr.description(), true, hasSetter, false);
|
||||
}
|
||||
} else {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Method " + method.getName()
|
||||
+ " must have a valid return type and zero parameters");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
AttributeEntry ae = attributesBuilder.get(attributeName);
|
||||
// is it a read method?
|
||||
if (!writeAttribute) {
|
||||
// we already have annotated field as read
|
||||
if (ae instanceof FieldAttributeEntry && ae.getInfo().isReadable()) {
|
||||
logger.warn("not adding annotated method " + method
|
||||
+ " since we already have read attribute");
|
||||
}
|
||||
// we already have annotated set method
|
||||
else if (ae instanceof MethodAttributeEntry) {
|
||||
MethodAttributeEntry mae = (MethodAttributeEntry) ae;
|
||||
if (mae.hasSetMethod()) {
|
||||
attributesBuilder.put(attributeName, new MethodAttributeEntry(mae.getInfo(), mae
|
||||
.getSetMethod(), method));
|
||||
}
|
||||
} // we don't have such entry
|
||||
else {
|
||||
attributesBuilder.put(attributeName, new MethodAttributeEntry(info, null, method));
|
||||
}
|
||||
}// is it a set method?
|
||||
else {
|
||||
if (ae instanceof FieldAttributeEntry) {
|
||||
// we already have annotated field as write
|
||||
if (ae.getInfo().isWritable()) {
|
||||
logger.warn("Not adding annotated method " + methodName
|
||||
+ " since we already have writable attribute");
|
||||
} else {
|
||||
// we already have annotated field as read
|
||||
// lets make the field writable
|
||||
Field f = ((FieldAttributeEntry) ae).getField();
|
||||
MBeanAttributeInfo i = new MBeanAttributeInfo(ae.getInfo().getName(),
|
||||
f.getType().getCanonicalName(), attr.description(), true,
|
||||
!Modifier.isFinal(f.getModifiers()), false);
|
||||
attributesBuilder.put(attributeName, new FieldAttributeEntry(i, f));
|
||||
}
|
||||
}
|
||||
// we already have annotated getOrIs method
|
||||
else if (ae instanceof MethodAttributeEntry) {
|
||||
MethodAttributeEntry mae = (MethodAttributeEntry) ae;
|
||||
if (mae.hasIsOrGetMethod()) {
|
||||
attributesBuilder.put(attributeName, new MethodAttributeEntry(info, method, mae
|
||||
.getIsOrGetMethod()));
|
||||
}
|
||||
} // we don't have such entry
|
||||
else {
|
||||
attributesBuilder.put(attributeName, new MethodAttributeEntry(info, method, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (method.isAnnotationPresent(ManagedOperation.class)) {
|
||||
ManagedOperation op = method.getAnnotation(ManagedOperation.class);
|
||||
String attName = method.getName();
|
||||
if (isSetMethod(method) || isGetMethod(method)) {
|
||||
attName = attName.substring(3);
|
||||
} else if (isIsMethod(method)) {
|
||||
attName = attName.substring(2);
|
||||
}
|
||||
// expose unless we already exposed matching attribute field
|
||||
boolean isAlreadyExposed = attributesBuilder.containsKey(attName);
|
||||
if (!isAlreadyExposed) {
|
||||
ops.add(new MBeanOperationInfo(op != null ? op.description() : "", method));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSetMethod(Method method) {
|
||||
return (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && method.getReturnType() == java.lang.Void.TYPE);
|
||||
}
|
||||
|
||||
private boolean isGetMethod(Method method) {
|
||||
return (method.getParameterTypes().length == 0 && method.getReturnType() != java.lang.Void.TYPE && method.getName().startsWith("get"));
|
||||
}
|
||||
|
||||
private boolean isIsMethod(Method method) {
|
||||
return (method.getParameterTypes().length == 0 && (method.getReturnType() == boolean.class || method.getReturnType() == Boolean.class) && method.getName().startsWith("is"));
|
||||
}
|
||||
|
||||
private void findFields(MapBuilder<String, AttributeEntry> attributesBuilder) {
|
||||
// traverse class hierarchy and find all annotated fields
|
||||
for (Class<?> clazz = getObject().getClass(); clazz != null; clazz = clazz.getSuperclass()) {
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
ManagedAttribute attr = field.getAnnotation(ManagedAttribute.class);
|
||||
if (attr != null) {
|
||||
String fieldName = renameToJavaCodingConvention(field.getName());
|
||||
MBeanAttributeInfo info = new MBeanAttributeInfo(fieldName, field.getType().getCanonicalName(),
|
||||
attr.description(), true, !Modifier.isFinal(field.getModifiers()) && attr.writable(), false);
|
||||
attributesBuilder.put(fieldName, new FieldAttributeEntry(info, field));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Attribute getNamedAttribute(String name) {
|
||||
Attribute result = null;
|
||||
AttributeEntry entry = attributes.get(name);
|
||||
if (entry != null) {
|
||||
MBeanAttributeInfo i = entry.getInfo();
|
||||
try {
|
||||
result = new Attribute(name, entry.invoke(null));
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Attribute " + name + " has r=" + i.isReadable() + ",w="
|
||||
+ i.isWritable() + ",is=" + i.isIs() + " and value "
|
||||
+ result.getValue());
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception while reading value of attribute " + name, e);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Did not find queried attribute with name " + name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean setNamedAttribute(Attribute attribute) {
|
||||
boolean result = false;
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Invoking set on attribute " + attribute.getName() + " with value " + attribute.getValue());
|
||||
|
||||
AttributeEntry entry = attributes.get(attribute.getName());
|
||||
if (entry != null) {
|
||||
try {
|
||||
entry.invoke(attribute);
|
||||
result = true;
|
||||
} catch (Exception e) {
|
||||
logger.warn("Exception while writing value for attribute " + attribute.getName(), e);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Could not invoke set on attribute " + attribute.getName() + " with value "
|
||||
+ attribute.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String renameToJavaCodingConvention(String fieldName) {
|
||||
if (fieldName.contains("_")) {
|
||||
Pattern p = Pattern.compile("_.");
|
||||
Matcher m = p.matcher(fieldName);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (m.find()) {
|
||||
m.appendReplacement(sb, fieldName.substring(m.end() - 1, m.end()).toUpperCase());
|
||||
}
|
||||
m.appendTail(sb);
|
||||
char first = sb.charAt(0);
|
||||
if (Character.isLowerCase(first)) {
|
||||
sb.setCharAt(0, Character.toUpperCase(first));
|
||||
}
|
||||
return sb.toString();
|
||||
} else {
|
||||
if (Character.isLowerCase(fieldName.charAt(0))) {
|
||||
return fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
|
||||
} else {
|
||||
return fieldName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodAttributeEntry implements AttributeEntry {
|
||||
|
||||
final MBeanAttributeInfo info;
|
||||
|
||||
final Method isOrGetmethod;
|
||||
|
||||
final Method setMethod;
|
||||
|
||||
public MethodAttributeEntry(final MBeanAttributeInfo info, final Method setMethod,
|
||||
final Method isOrGetMethod) {
|
||||
super();
|
||||
this.info = info;
|
||||
this.setMethod = setMethod;
|
||||
this.isOrGetmethod = isOrGetMethod;
|
||||
}
|
||||
|
||||
public Object invoke(Attribute a) throws Exception {
|
||||
if (a == null && isOrGetmethod != null)
|
||||
return isOrGetmethod.invoke(getObject());
|
||||
else if (a != null && setMethod != null)
|
||||
return setMethod.invoke(getObject(), a.getValue());
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public MBeanAttributeInfo getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public boolean hasIsOrGetMethod() {
|
||||
return isOrGetmethod != null;
|
||||
}
|
||||
|
||||
public boolean hasSetMethod() {
|
||||
return setMethod != null;
|
||||
}
|
||||
|
||||
public Method getIsOrGetMethod() {
|
||||
return isOrGetmethod;
|
||||
}
|
||||
|
||||
public Method getSetMethod() {
|
||||
return setMethod;
|
||||
}
|
||||
}
|
||||
|
||||
private class FieldAttributeEntry implements AttributeEntry {
|
||||
|
||||
private final MBeanAttributeInfo info;
|
||||
|
||||
private final Field field;
|
||||
|
||||
public FieldAttributeEntry(final MBeanAttributeInfo info, final Field field) {
|
||||
super();
|
||||
this.info = info;
|
||||
this.field = field;
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public Object invoke(Attribute a) throws Exception {
|
||||
if (a == null) {
|
||||
return field.get(getObject());
|
||||
} else {
|
||||
field.set(getObject(), a.getValue());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MBeanAttributeInfo getInfo() {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
private interface AttributeEntry {
|
||||
public Object invoke(Attribute a) throws Exception;
|
||||
|
||||
public MBeanAttributeInfo getInfo();
|
||||
}
|
||||
|
||||
public boolean isManagedResource() {
|
||||
return !attributes.isEmpty() || !operations.isEmpty();
|
||||
}
|
||||
|
||||
public String getFullObjectName() {
|
||||
return this.fullObjectName;
|
||||
}
|
||||
|
||||
public String getObjectName() {
|
||||
return this.objectName;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return this.groupName;
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.jmx.action;
|
||||
|
||||
import org.elasticsearch.ElasticSearchException;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class GetJmxServiceUrlAction extends AbstractComponent {
|
||||
|
||||
private final JmxService jmxService;
|
||||
|
||||
private final TransportService transportService;
|
||||
|
||||
private final ClusterService clusterService;
|
||||
|
||||
@Inject
|
||||
public GetJmxServiceUrlAction(Settings settings, JmxService jmxService,
|
||||
TransportService transportService, ClusterService clusterService) {
|
||||
super(settings);
|
||||
this.jmxService = jmxService;
|
||||
this.transportService = transportService;
|
||||
this.clusterService = clusterService;
|
||||
|
||||
transportService.registerHandler(GetJmxServiceUrlTransportHandler.ACTION, new GetJmxServiceUrlTransportHandler());
|
||||
}
|
||||
|
||||
public String obtainPublishUrl(final DiscoveryNode node) throws ElasticSearchException {
|
||||
if (clusterService.state().nodes().localNodeId().equals(node.id())) {
|
||||
return jmxService.publishUrl();
|
||||
} else {
|
||||
return transportService.submitRequest(node, GetJmxServiceUrlTransportHandler.ACTION, TransportRequest.Empty.INSTANCE, new FutureTransportResponseHandler<GetJmxServiceUrlResponse>() {
|
||||
@Override
|
||||
public GetJmxServiceUrlResponse newInstance() {
|
||||
return new GetJmxServiceUrlResponse();
|
||||
}
|
||||
}).txGet().url();
|
||||
}
|
||||
}
|
||||
|
||||
private class GetJmxServiceUrlTransportHandler extends BaseTransportRequestHandler<TransportRequest.Empty> {
|
||||
|
||||
static final String ACTION = "jmx/publishUrl";
|
||||
|
||||
@Override
|
||||
public TransportRequest.Empty newInstance() {
|
||||
return TransportRequest.Empty.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String executor() {
|
||||
return ThreadPool.Names.SAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(TransportRequest.Empty request, TransportChannel channel) throws Exception {
|
||||
channel.sendResponse(new GetJmxServiceUrlResponse(jmxService.publishUrl()));
|
||||
}
|
||||
}
|
||||
|
||||
static class GetJmxServiceUrlResponse extends TransportResponse {
|
||||
|
||||
private String url;
|
||||
|
||||
GetJmxServiceUrlResponse() {
|
||||
}
|
||||
|
||||
GetJmxServiceUrlResponse(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String url() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
url = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeString(url);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,7 +46,6 @@ import org.elasticsearch.common.io.CachedStreams;
|
|||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.network.NetworkService;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsModule;
|
||||
|
@ -70,8 +69,6 @@ import org.elasticsearch.indices.cluster.IndicesClusterStateService;
|
|||
import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache;
|
||||
import org.elasticsearch.indices.memory.IndexingMemoryController;
|
||||
import org.elasticsearch.indices.ttl.IndicesTTLService;
|
||||
import org.elasticsearch.jmx.JmxModule;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
import org.elasticsearch.monitor.MonitorModule;
|
||||
import org.elasticsearch.monitor.MonitorService;
|
||||
import org.elasticsearch.monitor.jvm.JvmInfo;
|
||||
|
@ -143,7 +140,6 @@ public final class InternalNode implements Node {
|
|||
modules.add(new NetworkModule());
|
||||
modules.add(new NodeCacheModule(settings));
|
||||
modules.add(new ScriptModule(settings));
|
||||
modules.add(new JmxModule(settings));
|
||||
modules.add(new EnvironmentModule(environment));
|
||||
modules.add(new NodeEnvironmentModule(nodeEnvironment));
|
||||
modules.add(new ClusterNameModule(settings));
|
||||
|
@ -217,7 +213,6 @@ public final class InternalNode implements Node {
|
|||
injector.getInstance(HttpServer.class).start();
|
||||
}
|
||||
injector.getInstance(BulkUdpService.class).start();
|
||||
injector.getInstance(JmxService.class).connectAndRegister(discoService.nodeDescription(), injector.getInstance(NetworkService.class));
|
||||
|
||||
logger.info("{{}}[{}]: started", Version.CURRENT, JvmInfo.jvmInfo().pid());
|
||||
|
||||
|
@ -259,7 +254,6 @@ public final class InternalNode implements Node {
|
|||
injector.getInstance(SearchService.class).stop();
|
||||
injector.getInstance(RestController.class).stop();
|
||||
injector.getInstance(TransportService.class).stop();
|
||||
injector.getInstance(JmxService.class).close();
|
||||
|
||||
for (Class<? extends LifecycleComponent> plugin : pluginsService.services()) {
|
||||
injector.getInstance(plugin).stop();
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.elasticsearch.common.inject.Module;
|
|||
import org.elasticsearch.common.inject.Modules;
|
||||
import org.elasticsearch.common.inject.SpawnModules;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
import org.elasticsearch.transport.local.LocalTransportModule;
|
||||
import org.elasticsearch.transport.netty.NettyTransportModule;
|
||||
|
||||
|
@ -54,8 +53,5 @@ public class TransportModule extends AbstractModule implements SpawnModules {
|
|||
@Override
|
||||
protected void configure() {
|
||||
bind(TransportService.class).asEagerSingleton();
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
bind(TransportServiceManagement.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.transport;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.jmx.MBean;
|
||||
import org.elasticsearch.jmx.ManagedAttribute;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@MBean(objectName = "service=transport", description = "Transport")
|
||||
public class TransportServiceManagement {
|
||||
|
||||
private final TransportService transportService;
|
||||
|
||||
@Inject
|
||||
public TransportServiceManagement(TransportService transportService) {
|
||||
this.transportService = transportService;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Transport address published to other nodes")
|
||||
public String getPublishAddress() {
|
||||
return transportService.boundAddress().publishAddress().toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Transport address bounded on")
|
||||
public String getBoundAddress() {
|
||||
return transportService.boundAddress().boundAddress().toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Total number of transport requests sent")
|
||||
public long getTotalNumberOfRequests() {
|
||||
return transportService.requestIds.get();
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.transport.local;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.jmx.MBean;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@MBean(objectName = "service=transport,transportType=local", description = "Local Transport")
|
||||
public class LocalTransportManagement {
|
||||
|
||||
private final LocalTransport transport;
|
||||
|
||||
@Inject
|
||||
public LocalTransportManagement(Transport transport) {
|
||||
this.transport = (LocalTransport) transport;
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ package org.elasticsearch.transport.local;
|
|||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
|
||||
/**
|
||||
|
@ -39,8 +38,5 @@ public class LocalTransportModule extends AbstractModule {
|
|||
protected void configure() {
|
||||
bind(LocalTransport.class).asEagerSingleton();
|
||||
bind(Transport.class).to(LocalTransport.class).asEagerSingleton();
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
bind(LocalTransportManagement.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon 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.transport.netty;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.jmx.MBean;
|
||||
import org.elasticsearch.jmx.ManagedAttribute;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@MBean(objectName = "service=transport,transportType=netty", description = "Netty Transport")
|
||||
public class NettyTransportManagement {
|
||||
|
||||
private final NettyTransport transport;
|
||||
|
||||
@Inject
|
||||
public NettyTransportManagement(Transport transport) {
|
||||
this.transport = (NettyTransport) transport;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Number of connections this node has to other nodes")
|
||||
public long getNumberOfOutboundConnections() {
|
||||
return transport.connectedNodes.size();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Number if IO worker threads")
|
||||
public int getWorkerCount() {
|
||||
return transport.workerCount;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Port(s) netty was configured to bind on")
|
||||
public String getPort() {
|
||||
return transport.port;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Host to bind to")
|
||||
public String getBindHost() {
|
||||
return transport.bindHost;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Host to publish")
|
||||
public String getPublishHost() {
|
||||
return transport.publishHost;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Connect timeout")
|
||||
public String getConnectTimeout() {
|
||||
return transport.connectTimeout.toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "TcpNoDelay")
|
||||
public Boolean getTcpNoDelay() {
|
||||
return transport.tcpNoDelay;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "TcpKeepAlive")
|
||||
public Boolean getTcpKeepAlive() {
|
||||
return transport.tcpKeepAlive;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "ReuseAddress")
|
||||
public Boolean getReuseAddress() {
|
||||
return transport.reuseAddress;
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "TcpSendBufferSize")
|
||||
public String getTcpSendBufferSize() {
|
||||
if (transport.tcpSendBufferSize == null) {
|
||||
return null;
|
||||
}
|
||||
return transport.tcpSendBufferSize.toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "TcpReceiveBufferSize")
|
||||
public String getTcpReceiveBufferSize() {
|
||||
if (transport.tcpReceiveBufferSize == null) {
|
||||
return null;
|
||||
}
|
||||
return transport.tcpReceiveBufferSize.toString();
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ package org.elasticsearch.transport.netty;
|
|||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.jmx.JmxService;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
|
||||
/**
|
||||
|
@ -39,8 +38,5 @@ public class NettyTransportModule extends AbstractModule {
|
|||
protected void configure() {
|
||||
bind(NettyTransport.class).asEagerSingleton();
|
||||
bind(Transport.class).to(NettyTransport.class).asEagerSingleton();
|
||||
if (JmxService.shouldExport(settings)) {
|
||||
bind(NettyTransportManagement.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue