blob: a62977980d188b5d4bf798a03303d4e52f54bf19 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.brooklyn.entity.java;
import java.util.concurrent.Callable;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.mgmt.Task;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.effector.AddSensor;
import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.core.sensor.http.HttpRequestSensor;
import org.apache.brooklyn.core.sensor.ssh.SshCommandSensor;
import org.apache.brooklyn.feed.jmx.JmxAttributePollConfig;
import org.apache.brooklyn.feed.jmx.JmxFeed;
import org.apache.brooklyn.feed.jmx.JmxHelper;
import org.apache.brooklyn.util.core.config.ConfigBag;
import org.apache.brooklyn.util.core.task.DynamicTasks;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.Beta;
import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
/**
* Configurable {@link org.apache.brooklyn.api.entity.EntityInitializer} which adds a JMX sensor feed to retrieve an
* <code>attribute</code> from a JMX <code>objectName</code>.
*
* @see SshCommandSensor
* @see HttpRequestSensor
*/
@Beta
public final class JmxAttributeSensor<T> extends AddSensor<T> {
private static final Logger LOG = LoggerFactory.getLogger(JmxAttributeSensor.class);
public static final ConfigKey<String> OBJECT_NAME = ConfigKeys.newStringConfigKey("objectName", "JMX object name for sensor lookup");
public static final ConfigKey<String> ATTRIBUTE = ConfigKeys.newStringConfigKey("attribute", "JMX attribute to poll in object");
public static final ConfigKey<Object> DEFAULT_VALUE = ConfigKeys.newConfigKey(Object.class, "defaultValue", "Default value for sensor; normally null");
protected final String objectName;
protected final String attribute;
protected final Object defaultValue;
public JmxAttributeSensor(final ConfigBag params) {
super(params);
objectName = Preconditions.checkNotNull(params.get(OBJECT_NAME), "objectName");
attribute = Preconditions.checkNotNull(params.get(ATTRIBUTE), "attribute");
defaultValue = params.get(DEFAULT_VALUE);
try {
ObjectName.getInstance(objectName);
} catch (MalformedObjectNameException mone) {
throw new IllegalArgumentException("Malformed JMX object name: " + objectName, mone);
}
}
@Override
public void apply(final EntityLocal entity) {
super.apply(entity);
if (entity instanceof UsesJmx) {
if (LOG.isDebugEnabled()) {
LOG.debug("Submitting task to add JMX sensor {} to {}", name, entity);
}
Task<Integer> jmxPortTask = DependentConfiguration.attributeWhenReady(entity, UsesJmx.JMX_PORT);
Task<JmxFeed> jmxFeedTask = Tasks.<JmxFeed>builder()
.description("Add JMX feed")
.body(new Callable<JmxFeed>() {
@Override
public JmxFeed call() throws Exception {
JmxHelper helper = new JmxHelper(entity);
Duration period = entity.getConfig(SENSOR_PERIOD);
JmxFeed feed = JmxFeed.builder()
.entity(entity)
.period(period)
.helper(helper)
.pollAttribute(new JmxAttributePollConfig<T>(sensor)
.objectName(objectName)
.attributeName(attribute)
.onFailureOrException(Functions.<T>constant((T) defaultValue)))
.build();
return feed;
}
})
.build();
DynamicTasks.submit(Tasks.sequential("Add JMX Sensor " + sensor.getName(), jmxPortTask, jmxFeedTask), entity);
} else {
throw new IllegalStateException(String.format("Entity %s does not support JMX", entity));
}
// TODO add entity shutdown hook to stop JmxFeed
}
}