Remove JMX connector creation flags, and JMX attributes

closes #2728
This commit is contained in:
Shay Banon 2013-03-04 16:12:18 -08:00
parent 774622abfb
commit cfd8bddde4
30 changed files with 0 additions and 1927 deletions

View File

@ -23,9 +23,6 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.settings.IndexSettings; 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() { public String nodeName() {
return indexSettings.get("name", ""); return indexSettings.get("name", "");
} }
@ManagedGroupName
private String managementGroupName() {
return buildIndexGroupName(index);
}
} }

View File

@ -23,7 +23,6 @@ import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.service.IndexService; import org.elasticsearch.index.service.IndexService;
import org.elasticsearch.index.service.InternalIndexService; import org.elasticsearch.index.service.InternalIndexService;
import org.elasticsearch.jmx.JmxService;
/** /**
* *
@ -39,8 +38,5 @@ public class IndexModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bind(IndexService.class).to(InternalIndexService.class).asEagerSingleton(); bind(IndexService.class).to(InternalIndexService.class).asEagerSingleton();
if (JmxService.shouldExport(settings)) {
bind(IndexServiceManagement.class).asEagerSingleton();
}
} }
} }

View File

@ -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();
}
}

View File

@ -55,7 +55,6 @@ import org.elasticsearch.index.search.stats.ShardSearchModule;
import org.elasticsearch.index.settings.IndexSettings; import org.elasticsearch.index.settings.IndexSettings;
import org.elasticsearch.index.settings.IndexSettingsService; import org.elasticsearch.index.settings.IndexSettingsService;
import org.elasticsearch.index.shard.IndexShardCreationException; import org.elasticsearch.index.shard.IndexShardCreationException;
import org.elasticsearch.index.shard.IndexShardManagement;
import org.elasticsearch.index.shard.IndexShardModule; import org.elasticsearch.index.shard.IndexShardModule;
import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.shard.service.IndexShard; import org.elasticsearch.index.shard.service.IndexShard;
@ -398,11 +397,6 @@ public class InternalIndexService extends AbstractIndexComponent implements Inde
// ignore // 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 // 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 // and close the shard so no operations are allowed to it
if (indexShard != null) { if (indexShard != null) {

View File

@ -23,9 +23,6 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.settings.IndexSettings; 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() { public String nodeName() {
return indexSettings.get("name", ""); return indexSettings.get("name", "");
} }
@ManagedGroupName
public String managementGroupName() {
return buildShardGroupName(shardId);
}
} }

View File

@ -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();
}
}
}

View File

@ -24,7 +24,6 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.shard.service.IndexShard; import org.elasticsearch.index.shard.service.IndexShard;
import org.elasticsearch.index.shard.service.InternalIndexShard; import org.elasticsearch.index.shard.service.InternalIndexShard;
import org.elasticsearch.index.warmer.ShardIndexWarmerService; import org.elasticsearch.index.warmer.ShardIndexWarmerService;
import org.elasticsearch.jmx.JmxService;
/** /**
* *
@ -44,9 +43,6 @@ public class IndexShardModule extends AbstractModule {
protected void configure() { protected void configure() {
bind(ShardId.class).toInstance(shardId); bind(ShardId.class).toInstance(shardId);
bind(IndexShard.class).to(InternalIndexShard.class).asEagerSingleton(); bind(IndexShard.class).to(InternalIndexShard.class).asEagerSingleton();
if (JmxService.shouldExport(settings)) {
bind(IndexShardManagement.class).asEagerSingleton();
}
bind(ShardIndexWarmerService.class).asEagerSingleton(); bind(ShardIndexWarmerService.class).asEagerSingleton();
} }
} }

View File

@ -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";
}
}
}

View File

@ -24,7 +24,6 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.store.distributor.Distributor; import org.elasticsearch.index.store.distributor.Distributor;
import org.elasticsearch.index.store.distributor.LeastUsedDistributor; import org.elasticsearch.index.store.distributor.LeastUsedDistributor;
import org.elasticsearch.index.store.distributor.RandomWeightedDistributor; import org.elasticsearch.index.store.distributor.RandomWeightedDistributor;
import org.elasticsearch.jmx.JmxService;
/** /**
* *
@ -50,9 +49,6 @@ public class StoreModule extends AbstractModule {
protected void configure() { protected void configure() {
bind(DirectoryService.class).to(indexStore.shardDirectory()).asEagerSingleton(); bind(DirectoryService.class).to(indexStore.shardDirectory()).asEagerSingleton();
bind(Store.class).asEagerSingleton(); bind(Store.class).asEagerSingleton();
if (JmxService.shouldExport(settings)) {
bind(StoreManagement.class).asEagerSingleton();
}
if (distributor == null) { if (distributor == null) {
distributor = loadDistributor(settings); distributor = loadDistributor(settings);
} }

View File

@ -353,7 +353,6 @@ public class InternalIndicesService extends AbstractLifecycleComponent<IndicesSe
indexInjector.getInstance(IndexFieldDataService.class).clear(); indexInjector.getInstance(IndexFieldDataService.class).clear();
indexInjector.getInstance(AnalysisService.class).close(); indexInjector.getInstance(AnalysisService.class).close();
indexInjector.getInstance(IndexEngine.class).close(); indexInjector.getInstance(IndexEngine.class).close();
indexInjector.getInstance(IndexServiceManagement.class).close();
indexInjector.getInstance(IndexGateway.class).close(delete); indexInjector.getInstance(IndexGateway.class).close(delete);
indexInjector.getInstance(MapperService.class).close(); indexInjector.getInstance(MapperService.class).close();

View File

@ -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();
}

View File

@ -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);
}
});
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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 "";
}

View File

@ -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;
}

View File

@ -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 {
}

View File

@ -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 "";
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -46,7 +46,6 @@ import org.elasticsearch.common.io.CachedStreams;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule; 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.fielddata.cache.IndicesFieldDataCache;
import org.elasticsearch.indices.memory.IndexingMemoryController; import org.elasticsearch.indices.memory.IndexingMemoryController;
import org.elasticsearch.indices.ttl.IndicesTTLService; 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.MonitorModule;
import org.elasticsearch.monitor.MonitorService; import org.elasticsearch.monitor.MonitorService;
import org.elasticsearch.monitor.jvm.JvmInfo; import org.elasticsearch.monitor.jvm.JvmInfo;
@ -143,7 +140,6 @@ public final class InternalNode implements Node {
modules.add(new NetworkModule()); modules.add(new NetworkModule());
modules.add(new NodeCacheModule(settings)); modules.add(new NodeCacheModule(settings));
modules.add(new ScriptModule(settings)); modules.add(new ScriptModule(settings));
modules.add(new JmxModule(settings));
modules.add(new EnvironmentModule(environment)); modules.add(new EnvironmentModule(environment));
modules.add(new NodeEnvironmentModule(nodeEnvironment)); modules.add(new NodeEnvironmentModule(nodeEnvironment));
modules.add(new ClusterNameModule(settings)); modules.add(new ClusterNameModule(settings));
@ -217,7 +213,6 @@ public final class InternalNode implements Node {
injector.getInstance(HttpServer.class).start(); injector.getInstance(HttpServer.class).start();
} }
injector.getInstance(BulkUdpService.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()); 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(SearchService.class).stop();
injector.getInstance(RestController.class).stop(); injector.getInstance(RestController.class).stop();
injector.getInstance(TransportService.class).stop(); injector.getInstance(TransportService.class).stop();
injector.getInstance(JmxService.class).close();
for (Class<? extends LifecycleComponent> plugin : pluginsService.services()) { for (Class<? extends LifecycleComponent> plugin : pluginsService.services()) {
injector.getInstance(plugin).stop(); injector.getInstance(plugin).stop();

View File

@ -25,7 +25,6 @@ import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.Modules; import org.elasticsearch.common.inject.Modules;
import org.elasticsearch.common.inject.SpawnModules; import org.elasticsearch.common.inject.SpawnModules;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.jmx.JmxService;
import org.elasticsearch.transport.local.LocalTransportModule; import org.elasticsearch.transport.local.LocalTransportModule;
import org.elasticsearch.transport.netty.NettyTransportModule; import org.elasticsearch.transport.netty.NettyTransportModule;
@ -54,8 +53,5 @@ public class TransportModule extends AbstractModule implements SpawnModules {
@Override @Override
protected void configure() { protected void configure() {
bind(TransportService.class).asEagerSingleton(); bind(TransportService.class).asEagerSingleton();
if (JmxService.shouldExport(settings)) {
bind(TransportServiceManagement.class).asEagerSingleton();
}
} }
} }

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -21,7 +21,6 @@ package org.elasticsearch.transport.local;
import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.jmx.JmxService;
import org.elasticsearch.transport.Transport; import org.elasticsearch.transport.Transport;
/** /**
@ -39,8 +38,5 @@ public class LocalTransportModule extends AbstractModule {
protected void configure() { protected void configure() {
bind(LocalTransport.class).asEagerSingleton(); bind(LocalTransport.class).asEagerSingleton();
bind(Transport.class).to(LocalTransport.class).asEagerSingleton(); bind(Transport.class).to(LocalTransport.class).asEagerSingleton();
if (JmxService.shouldExport(settings)) {
bind(LocalTransportManagement.class).asEagerSingleton();
}
} }
} }

View File

@ -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();
}
}

View File

@ -21,7 +21,6 @@ package org.elasticsearch.transport.netty;
import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.jmx.JmxService;
import org.elasticsearch.transport.Transport; import org.elasticsearch.transport.Transport;
/** /**
@ -39,8 +38,5 @@ public class NettyTransportModule extends AbstractModule {
protected void configure() { protected void configure() {
bind(NettyTransport.class).asEagerSingleton(); bind(NettyTransport.class).asEagerSingleton();
bind(Transport.class).to(NettyTransport.class).asEagerSingleton(); bind(Transport.class).to(NettyTransport.class).asEagerSingleton();
if (JmxService.shouldExport(settings)) {
bind(NettyTransportManagement.class).asEagerSingleton();
}
} }
} }