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

org.apache.solr.metrics.reporters.jmx.JmxObjectNameFactory Maven / Gradle / Ivy

There is a newer version: 9.7.0
Show newest version
/*
 * 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.solr.metrics.reporters.jmx;

import com.codahale.metrics.jmx.ObjectNameFactory;
import java.util.Arrays;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.solr.metrics.SolrMetricInfo;

/** Factory to create MBean names for a given metric. */
public class JmxObjectNameFactory implements ObjectNameFactory {

  private final String domain;
  private final String[] subdomains;
  private final String reporterName;
  private final String[] props;

  /**
   * Create ObjectName factory.
   *
   * @param reporterName name of the reporter
   * @param domain JMX domain name
   * @param additionalProperties additional properties as key, value pairs.
   */
  public JmxObjectNameFactory(String reporterName, String domain, String... additionalProperties) {
    this.reporterName = reporterName.replace(":", "_");
    this.domain = domain;
    this.subdomains = domain.replace(":", "_").split("\\.");
    if (additionalProperties != null && (additionalProperties.length % 2) != 0) {
      throw new IllegalArgumentException(
          "additionalProperties length must be even: " + Arrays.toString(additionalProperties));
    }
    this.props = additionalProperties;
  }

  /** Return current domain. */
  public String getDomain() {
    return domain;
  }

  /** Return current reporterName. */
  public String getReporterName() {
    return reporterName;
  }

  /**
   * Create a hierarchical name.
   *
   * @param type metric class, eg. "counters", may be null for non-metric MBeans
   * @param currentDomain JMX domain
   * @param name object name
   */
  @Override
  public ObjectName createName(String type, String currentDomain, String name) {
    SolrMetricInfo metricInfo = SolrMetricInfo.of(name);
    String safeName = metricInfo != null ? metricInfo.name : name;
    safeName = safeName.replace(":", "_");
    // It turns out that ObjectName(String) mostly preserves key ordering
    // as specified in the constructor (except for the 'type' key that ends
    // up at top level) - unlike ObjectName(String, Map) constructor
    // that seems to have a mind of its own...
    StringBuilder sb = new StringBuilder();
    if (domain.equals(currentDomain)) {
      if (subdomains != null && subdomains.length > 1) {
        // use only first segment as domain
        sb.append(subdomains[0]);
        sb.append(':');
        // use remaining segments as properties
        for (int i = 1; i < subdomains.length; i++) {
          if (i > 1) {
            sb.append(',');
          }
          sb.append("dom");
          sb.append(String.valueOf(i));
          sb.append('=');
          sb.append(subdomains[i]);
        }
        sb.append(','); // separate from other properties
      } else {
        sb.append(currentDomain.replace(":", "_"));
        sb.append(':');
      }
    } else {
      sb.append(currentDomain);
      sb.append(':');
    }
    if (props != null && props.length > 0) {
      boolean added = false;
      for (int i = 0; i < props.length; i += 2) {
        if (props[i] == null || props[i].isEmpty()) {
          continue;
        }
        if (props[i + 1] == null || props[i + 1].isEmpty()) {
          continue;
        }
        sb.append(',');
        sb.append(props[i]);
        sb.append('=');
        sb.append(props[i + 1]);
        added = true;
      }
      if (added) {
        sb.append(',');
      }
    }
    if (metricInfo != null) {
      sb.append("category=");
      sb.append(metricInfo.category.toString());
      if (metricInfo.scope != null) {
        sb.append(",scope=");
        sb.append(metricInfo.scope);
      }
      // we could also split by type, but don't call it 'type' :)
      // if (type != null) {
      //   sb.append(",class=");
      //   sb.append(type);
      // }
      sb.append(",name=");
      sb.append(safeName);
    } else {
      // make dotted names into hierarchies
      String[] path = safeName.split("\\.");
      for (int i = 0; i < path.length - 1; i++) {
        if (i > 0) {
          sb.append(',');
        }
        sb.append("name");
        sb.append(String.valueOf(i));
        sb.append('=');
        sb.append(path[i]);
      }
      if (path.length > 1) {
        sb.append(',');
      }
      // split by type
      // if (type != null) {
      //   sb.append("class=");
      //   sb.append(type);
      // }
      sb.append("name=");
      sb.append(path[path.length - 1]);
    }

    ObjectName objectName;

    try {
      objectName = new ObjectName(sb.toString());
    } catch (MalformedObjectNameException e) {
      throw new RuntimeException(sb.toString(), e);
    }

    return objectName;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy