jmx functionality

This commit is contained in:
Mark Pollack
2011-02-03 12:24:50 -05:00
parent 3a47f192d7
commit 96fd017123
12 changed files with 607 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;
import com.mongodb.DB;
import com.mongodb.Mongo;
/**
* Mongo server administration exposed via JMX annotations
*
* @author Mark Pollack
*
*/
@ManagedResource(description="Mongo Admin Operations")
public class MongoAdmin implements MongoAdminOperations {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private Mongo mongo;
private String username;
private String password;
public MongoAdmin(Mongo mongo) {
this.mongo = mongo;
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#dropDatabase(java.lang.String)
*/
@ManagedOperation
public void dropDatabase(String databaseName) {
mongo.getDB(databaseName).dropDatabase();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#createDatabase(java.lang.String)
*/
@ManagedOperation
public void createDatabase(String databaseName) {
mongo.getDB(databaseName);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#getDatabaseStats(java.lang.String)
*/
@ManagedOperation
public String getDatabaseStats(String databaseName) {
return mongo.getDB("testAdminDb").getStats().toString();
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*/
public void setPassword(String password) {
this.password = password;
}
public DB getDb(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
}

View File

@@ -0,0 +1,16 @@
package org.springframework.data.document.mongodb;
import org.springframework.jmx.export.annotation.ManagedOperation;
public interface MongoAdminOperations {
@ManagedOperation
public abstract void dropDatabase(String databaseName);
@ManagedOperation
public abstract void createDatabase(String databaseName);
@ManagedOperation
public abstract String getDatabaseStats(String databaseName);
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb.monitor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.document.mongodb.MongoDbUtils;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
/**
* Base class to encapsulate common configuration settings when connecting to a database
*
* @author Mark Pollack
*
*/
public abstract class AbstractMonitor {
private final Log logger = LogFactory.getLog(getClass());
protected Mongo mongo;
private String username;
private String password;
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*/
public void setPassword(String password) {
this.password = password;
}
public CommandResult getServerStatus() {
CommandResult result = getDb("admin").command("serverStatus");
if (!result.ok()) {
logger.error("Could not query for server status. Command Result = " + result);
throw new MongoException("could not query for server status. Command Result = " + result);
}
return result;
}
public DB getDb(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb.monitor;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.support.MetricType;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
@ManagedResource(description="Mongo Global Lock Metrics")
public class GlobalLockMetrics extends AbstractMonitor {
public GlobalLockMetrics(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Total time")
public double getTotalTime() {
return getGlobalLockData("totalTime", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Lock time", unit="seconds")
public double getLockTime() {
return getGlobalLockData("lockTime", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Lock time")
public double getLockTimeRatio() {
return getGlobalLockData("ratio", java.lang.Double.class);
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Current Queue")
public int getCurrentQueueTotal() {
return getCurrentQueue("total");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Reader Queue")
public int getCurrentQueueReaders() {
return getCurrentQueue("readers");
}
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Writer Queue")
public int getCurrentQueueWriters() {
return getCurrentQueue("writers");
}
@SuppressWarnings("unchecked")
private <T> T getGlobalLockData(String key, Class<T> targetClass) {
DBObject globalLock = (DBObject) getServerStatus().get("globalLock");
Object o = globalLock.get("totalTime");
return (T) globalLock.get(key);
}
private int getCurrentQueue(String key) {
DBObject globalLock = (DBObject) getServerStatus().get("globalLock");
DBObject currentQueue = (DBObject) globalLock.get("currentQueue");
Object o = currentQueue.get("total");
return (Integer) currentQueue.get(key);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb.monitor;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.support.MetricType;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
@ManagedResource(description="Mongo Operation Counters")
public class OperationCounters extends AbstractMonitor {
public OperationCounters(Mongo mongo) {
this.mongo = mongo;
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Insert operation count")
public int getInsertCount() {
return getOpCounter("insert");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Query operation count")
public int getQueryCount() {
return getOpCounter("query");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Update operation count")
public int getUpdateCount() {
return getOpCounter("update");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Delete operation count")
public int getDeleteCount() {
return getOpCounter("delete");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "GetMore operation count")
public int getGetMoreCount() {
return getOpCounter("getmore");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Command operation count")
public int getCommandCount() {
return getOpCounter("command");
}
private int getOpCounter(String key) {
DBObject opCounters = (DBObject) getServerStatus().get("opcounters");
return (Integer) opCounters.get(key);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb.monitor;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.support.MetricType;
import com.mongodb.CommandResult;
import com.mongodb.Mongo;
/**
* Expose basic server information
*
* @author Mark Pollack
*
*/
@ManagedResource(description="Mongo Server Information")
public class ServerInfo extends AbstractMonitor {
public ServerInfo(Mongo mongo) {
this.mongo = mongo;
}
@ManagedOperation(description="Server host name")
public String getHostName() throws UnknownHostException {
return InetAddress.getLocalHost().getHostName();
}
@ManagedMetric(displayName="Uptime Estimate")
public double getUptimeEstimate()
{
return (Double)getServerStatus().get("uptimeEstimate");
}
@ManagedOperation(description="MongoDB Server Version")
public String getVersion() {
return (String) getServerStatus().get("version");
}
@ManagedOperation(description="Local Time")
public String getLocalTime() {
return (String) getServerStatus().get("localTime");
}
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Server uptime in seconds", unit="seconds")
public double getUptime() {
return (Double) getServerStatus().get("uptime");
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Server application than can be run as an app or unit test.
*
* @author Mark Pollack
*/
public class JmxServer {
public static void main(String[] args) {
new JmxServer().run();
}
public void run() {
new ClassPathXmlApplicationContext(new String[] {"infrastructure.xml", "server-jmx.xml"} );
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.Mongo;
/**
*
* This test class assumes that you are already running the MongoDB server.
*
* @author Mark Pollack
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class MongoAdminIntegrationTests {
private static Log logger = LogFactory.getLog(MongoAdminIntegrationTests.class);
private MongoAdminOperations mongoAdmin;
private DB testAdminDb;
@Autowired
Mongo mongo;
@Before
public void setUp() {
mongo.getDB("testAdminDb").dropDatabase();
testAdminDb = mongo.getDB("testAdminDb");
}
@Test
public void serverStats() {
//CommandResult result = testAdminDb.getStats();
CommandResult result = mongo.getDB("admin").command("serverStatus");
logger.info("stats = " + result);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed 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.springframework.data.document.mongodb.monitor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.CommandResult;
import com.mongodb.DB;
import com.mongodb.Mongo;
/**
*
* This test class assumes that you are already running the MongoDB server.
*
* @author Mark Pollack
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class MongoMonitorIntegrationTests {
@Autowired
Mongo mongo;
@Test
public void serverInfo() {
ServerInfo serverInfo = new ServerInfo(mongo);
String version = serverInfo.getVersion();
Assert.isTrue(StringUtils.hasText("1."));
}
@Test
public void operationCounters() {
OperationCounters operationCounters = new OperationCounters(mongo);
operationCounters.getInsertCount();
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
<property name="host" value="localhost" />
<property name="port" value="27017" />
</bean>
</beans>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="mongoAdmin" class="org.springframework.data.document.mongodb.MongoAdmin" autowire="constructor"/>
<bean id="serverInfo" class="org.springframework.data.document.mongodb.monitor.ServerInfo" autowire="constructor"/>
<bean id="operationCounters" class="org.springframework.data.document.mongodb.monitor.OperationCounters" autowire="constructor"/>
<bean id="globalLockMetrics" class="org.springframework.data.document.mongodb.monitor.GlobalLockMetrics" autowire="constructor"/>
<context:mbean-export/>
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
p:port="1099" />
<!-- Expose JMX over RMI -->
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry"
p:objectName="connector:name=rmi"
p:serviceUrl="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector" />
</beans>

View File

@@ -9,6 +9,7 @@ Import-Template:
org.springframework.core.*;version="[3.0.0, 4.0.0)",
org.springframework.dao.*;version="[3.0.0, 4.0.0)",
org.springframework.util.*;version="[3.0.0, 4.0.0)",
org.springframework.jmx.export.*;version="[3.0.0, 4.0.0)",
org.springframework.transaction.*;version="[3.0.0, 4.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.domain.*;version="[1.0.0, 2.0.0)",