All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.jmxtrans.model.Query Maven / Gradle / Ivy

There is a newer version: 272
Show newest version
/**
 * The MIT License
 * Copyright © 2010 JmxTrans team
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.googlecode.jmxtrans.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.googlecode.jmxtrans.model.naming.typename.PrependingTypeNameValuesStringBuilder;
import com.googlecode.jmxtrans.model.naming.typename.TypeNameValuesStringBuilder;
import com.googlecode.jmxtrans.model.naming.typename.UseAllTypeNameValuesStringBuilder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import javax.annotation.concurrent.ThreadSafe;
import javax.management.AttributeList;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import java.io.IOException;
import java.rmi.UnmarshalException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion.NON_NULL;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.collect.ImmutableList.copyOf;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static java.util.Arrays.asList;

/**
 * Represents a JMX Query to ask for obj, attr and one or more keys.
 *
 * @author jon
 */
@JsonSerialize(include = NON_NULL)
@JsonPropertyOrder(value = {"obj", "attr", "typeNames", "resultAlias", "keys", "allowDottedKeys", "useAllTypeNames", "outputWriters"})
@ThreadSafe
@EqualsAndHashCode(exclude = {"outputWriters", "outputWriterInstances"})
@ToString(exclude = {"outputWriters", "typeNameValuesStringBuilder"})
public class Query {

	private static final Logger logger = LoggerFactory.getLogger(Query.class);

	/** The JMX object representation: java.lang:type=Memory */
	@Nonnull @Getter private final ObjectName objectName;
	@Nonnull @Getter private final ImmutableList keys;

	@Nonnull @Getter private final ImmutableList attr;

	/**
	 * The list of type names used in a JMX bean string when querying with a
	 * wildcard which is used to expose the actual type name value to the key
	 * string. e.g. for this JMX name
	 * 

* typeName=name=PS Eden Space,type=MemoryPool *

* If you add a typeName("name"), then it'll retrieve 'PS Eden Space' from * the string. *

* The order of the elements of this set matches the order provided by the * user. */ @Getter private final ImmutableSet typeNames; /** * The alias allows you to specify what you would like the results of the * query to go into. */ @Getter private final String resultAlias; /** * The useObjDomainAsKey property allows you to specify the use of the Domain portion of the Object Name * as part of the output key instead of using the ClassName of the MBean which is the default behavior. */ @Getter private final boolean useObjDomainAsKey; @Getter private final boolean allowDottedKeys; @Getter private final boolean useAllTypeNames; @Nonnull @Getter private final ImmutableList outputWriters; @Nonnull @Getter private final Iterable outputWriterInstances; private final TypeNameValuesStringBuilder typeNameValuesStringBuilder; @JsonCreator public Query( @JsonProperty("obj") String obj, @JsonProperty("keys") List keys, @JsonProperty("attr") List attr, @JsonProperty("typeNames") List typeNames, @JsonProperty("resultAlias") String resultAlias, @JsonProperty("useObjDomainAsKey") boolean useObjDomainAsKey, @JsonProperty("allowDottedKeys") boolean allowDottedKeys, @JsonProperty("useAllTypeNames") boolean useAllTypeNames, @JsonProperty("outputWriters") List outputWriters ) { // For typeName, note the using copyOf does not change the order of // the elements. this(obj, keys, attr, ImmutableSet.copyOf(firstNonNull(typeNames, Collections.emptySet())), resultAlias, useObjDomainAsKey, allowDottedKeys, useAllTypeNames, outputWriters, ImmutableList.of()); } public Query( String obj, List keys, List attr, Set typeNames, String resultAlias, boolean useObjDomainAsKey, boolean allowDottedKeys, boolean useAllTypeNames, List outputWriters ) { this(obj, keys, attr, typeNames, resultAlias, useObjDomainAsKey, allowDottedKeys, useAllTypeNames, outputWriters, ImmutableList.of()); } public Query( String obj, List keys, List attr, Set typeNames, String resultAlias, boolean useObjDomainAsKey, boolean allowDottedKeys, boolean useAllTypeNames, ImmutableList outputWriters ) { this(obj, keys, attr, typeNames, resultAlias, useObjDomainAsKey, allowDottedKeys, useAllTypeNames, ImmutableList.of(), outputWriters); } private Query( String obj, List keys, List attr, Set typeNames, String resultAlias, boolean useObjDomainAsKey, boolean allowDottedKeys, boolean useAllTypeNames, List outputWriterFactories, List outputWriters ) { try { this.objectName = new ObjectName(obj); } catch (MalformedObjectNameException e) { throw new IllegalArgumentException("Invalid object name: " + obj, e); } this.attr = copyOf(firstNonNull(attr, Collections.emptyList())); this.resultAlias = resultAlias; this.useObjDomainAsKey = firstNonNull(useObjDomainAsKey, false); this.keys = copyOf(firstNonNull(keys, Collections.emptyList())); this.allowDottedKeys = allowDottedKeys; this.useAllTypeNames = useAllTypeNames; this.outputWriters = copyOf(firstNonNull(outputWriterFactories, ImmutableList.of())); // We need to preserve the order of typeNames. So note that copyOf // does not mess with the order. this.typeNames = ImmutableSet.copyOf(firstNonNull(typeNames, Collections.emptySet())); this.typeNameValuesStringBuilder = makeTypeNameValuesStringBuilder(); this.outputWriterInstances = copyOf(firstNonNull(outputWriters, ImmutableList.of())); } public String makeTypeNameValueString(List typeNames, String typeNameStr) { return this.typeNameValuesStringBuilder.build(typeNames, typeNameStr); } public Iterable queryNames(MBeanServerConnection mbeanServer) throws IOException { return mbeanServer.queryNames(objectName, null); } public Iterable fetchResults(MBeanServerConnection mbeanServer, ObjectName queryName) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException { ObjectInstance oi = mbeanServer.getObjectInstance(queryName); List attributes; if (attr.isEmpty()) { attributes = new ArrayList<>(); MBeanInfo info = mbeanServer.getMBeanInfo(queryName); for (MBeanAttributeInfo attrInfo : info.getAttributes()) { attributes.add(attrInfo.getName()); } } else { attributes = attr; } try { if (!attributes.isEmpty()) { logger.debug("Executing queryName [{}] from query [{}]", queryName.getCanonicalName(), this); AttributeList al = mbeanServer.getAttributes(queryName, attributes.toArray(new String[attributes.size()])); return new JmxResultProcessor(this, oi, al.asList(), oi.getClassName(), queryName.getDomain()).getResults(); } } catch (UnmarshalException ue) { if ((ue.getCause() != null) && (ue.getCause() instanceof ClassNotFoundException)) { logger.debug("Bad unmarshall, continuing. This is probably ok and due to something like this: " + "http://ehcache.org/xref/net/sf/ehcache/distribution/RMICacheManagerPeerListener.html#52", ue.getMessage()); } else { throw ue; } } return ImmutableList.of(); } private TypeNameValuesStringBuilder makeTypeNameValuesStringBuilder() { String separator = isAllowDottedKeys() ? "." : TypeNameValuesStringBuilder.DEFAULT_SEPARATOR; Set typeNames = getTypeNames(); if (isUseAllTypeNames()) { return new UseAllTypeNameValuesStringBuilder(separator); } else if (typeNames != null && !typeNames.isEmpty()) { return new PrependingTypeNameValuesStringBuilder(separator, new ArrayList<>(typeNames)); } else { return new TypeNameValuesStringBuilder(separator); } } public static Builder builder() { return new Builder(); } public static Builder builder(Query query) { return new Builder(query); } public void runOutputWritersForQuery(Server server, Iterable results) throws Exception { for (OutputWriter writer : getOutputWriterInstances()) { writer.doWrite(server, this, results); } logger.debug("Finished running outputWriters for query: {}", this); } @NotThreadSafe @Accessors(chain = true) public static final class Builder { @Setter private String obj; private final List attr = newArrayList(); @Setter private String resultAlias; private final List keys = newArrayList(); @Setter private boolean useObjDomainAsKey; @Setter private boolean allowDottedKeys; @Setter private boolean useAllTypeNames; private final List outputWriterFactories = newArrayList(); private final List outputWriters = newArrayList(); // We need to pick an order preserving Set implementation here to // avoid unpredictable ordering of typeNames. private final Set typeNames = newLinkedHashSet(); private Builder() {} /** This builder does NOT copy output writers from the given query. */ private Builder(Query query) { this.obj = query.objectName.toString(); this.attr.addAll(query.attr); this.resultAlias = query.resultAlias; this.keys.addAll(query.keys); this.useObjDomainAsKey = query.useObjDomainAsKey; this.allowDottedKeys = query.allowDottedKeys; this.useAllTypeNames = query.useAllTypeNames; this.typeNames.addAll(query.typeNames); } public Builder addAttr(String... attr) { this.attr.addAll(asList(attr)); return this; } public Builder addKey(String keys) { return addKeys(keys); } public Builder addKeys(String... keys) { this.keys.addAll(asList(keys)); return this; } public Builder addOutputWriterFactory(OutputWriterFactory outputWriterFactory) { return addOutputWriterFactories(outputWriterFactory); } public Builder addOutputWriterFactories(OutputWriterFactory... outputWriterFactories) { this.outputWriterFactories.addAll(asList(outputWriterFactories)); return this; } public Builder addOutputWriters(Collection outputWriters) { this.outputWriters.addAll(outputWriters); return this; } public Builder setTypeNames(Collection typeNames) { this.typeNames.addAll(typeNames); return this; } public Query build() { if (!outputWriterFactories.isEmpty()) { return new Query( this.obj, this.keys, this.attr, this.typeNames, this.resultAlias, this.useObjDomainAsKey, this.allowDottedKeys, this.useAllTypeNames, this.outputWriterFactories ); } return new Query( this.obj, this.keys, this.attr, this.typeNames, this.resultAlias, this.useObjDomainAsKey, this.allowDottedKeys, this.useAllTypeNames, copyOf(this.outputWriters) ); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy