001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 * */
018package org.apache.hadoop.hbase.util;
019
020import java.beans.IntrospectionException;
021import java.io.IOException;
022import java.io.PrintWriter;
023import java.io.StringWriter;
024import java.lang.management.GarbageCollectorMXBean;
025import java.lang.management.ManagementFactory;
026import java.lang.management.MemoryPoolMXBean;
027import java.lang.management.RuntimeMXBean;
028import java.util.Hashtable;
029import java.util.List;
030import java.util.Set;
031import javax.management.InstanceNotFoundException;
032import javax.management.MBeanAttributeInfo;
033import javax.management.MBeanInfo;
034import javax.management.MBeanServer;
035import javax.management.MalformedObjectNameException;
036import javax.management.ObjectName;
037import javax.management.ReflectionException;
038import javax.management.openmbean.CompositeData;
039import org.apache.yetus.audience.InterfaceAudience;
040import org.slf4j.Logger;
041import org.slf4j.LoggerFactory;
042
043@InterfaceAudience.Private
044public final class JSONMetricUtil {
045
046  private static final Logger LOG = LoggerFactory.getLogger(JSONMetricUtil.class);
047
048  private static MBeanServer mbServer = ManagementFactory.getPlatformMBeanServer();
049  // MBeans ObjectName domain names
050  public static final String JAVA_LANG_DOMAIN = "java.lang";
051  public static final String JAVA_NIO_DOMAIN = "java.nio";
052  public static final String SUN_MGMT_DOMAIN = "com.sun.management";
053  public static final String HADOOP_DOMAIN = "Hadoop";
054
055  // MBeans ObjectName properties key names
056  public static final String TYPE_KEY = "type";
057  public static final String NAME_KEY = "name";
058  public static final String SERVICE_KEY = "service";
059  public static final String SUBSYSTEM_KEY = "sub";
060
061  /**
062   * Utility for getting metric values. Collection of static methods intended for easier access to
063   * metric values.
064   */
065  private JSONMetricUtil() {
066    // Not to be called
067  }
068
069  public static MBeanAttributeInfo[] getMBeanAttributeInfo(ObjectName bean)
070      throws IntrospectionException, InstanceNotFoundException, ReflectionException,
071      IntrospectionException, javax.management.IntrospectionException {
072    MBeanInfo mbinfo = mbServer.getMBeanInfo(bean);
073    return mbinfo.getAttributes();
074  }
075
076  public static Object getValueFromMBean(ObjectName bean, String attribute) {
077    Object value = null;
078    try {
079      value = mbServer.getAttribute(bean, attribute);
080    } catch (Exception e) {
081      LOG.error("Unable to get value from MBean= " + bean.toString() + "for attribute=" +
082        attribute + " " + e.getMessage());
083    }
084    return value;
085  }
086
087  /**
088   * Returns a subset of mbeans defined by qry. Modeled after DumpRegionServerMetrics#dumpMetrics.
089   * Example: String qry= "java.lang:type=Memory"
090   * @throws MalformedObjectNameException if json have bad format
091   * @throws IOException /
092   * @return String representation of json array.
093   */
094  public static String dumpBeanToString(String qry)
095      throws MalformedObjectNameException, IOException {
096    StringWriter sw = new StringWriter(1024 * 100); // Guess this size
097    try (PrintWriter writer = new PrintWriter(sw)) {
098      JSONBean dumper = new JSONBean();
099      try (JSONBean.Writer jsonBeanWriter = dumper.open(writer)) {
100        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
101        jsonBeanWriter.write(mbeanServer, new ObjectName(qry), null, false);
102      }
103    }
104    sw.close();
105    return sw.toString();
106  }
107
108  /**
109   * Method for building map used for constructing ObjectName. Mapping is done with arrays indices
110   * @param keys Map keys
111   * @param values Map values
112   * @return Map or null if arrays are empty * or have different number of elements
113   */
114  public static Hashtable<String, String> buldKeyValueTable(String[] keys, String[] values) {
115    if (keys.length != values.length) {
116      LOG.error("keys and values arrays must be same size");
117      return null;
118    }
119    if (keys.length == 0 || values.length == 0) {
120      LOG.error("keys and values arrays can not be empty;");
121      return null;
122    }
123    Hashtable<String, String> table = new Hashtable<>();
124    for (int i = 0; i < keys.length; i++) {
125      table.put(keys[i], values[i]);
126    }
127    return table;
128  }
129
130  public static ObjectName buildObjectName(String pattern) throws MalformedObjectNameException {
131    return new ObjectName(pattern);
132  }
133
134  public static ObjectName buildObjectName(String domain, Hashtable<String, String> keyValueTable)
135      throws MalformedObjectNameException {
136    return new ObjectName(domain, keyValueTable);
137  }
138
139  public static Set<ObjectName> getRegistredMBeans(ObjectName name, MBeanServer mbs) {
140    return mbs.queryNames(name, null);
141  }
142
143  public static String getProcessPID() {
144    return ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
145  }
146
147  public static String getCommmand() throws MalformedObjectNameException, IOException {
148    RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
149    return runtimeBean.getSystemProperties().get("sun.java.command");
150  }
151
152  public static List<GarbageCollectorMXBean> getGcCollectorBeans() {
153    List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
154    return gcBeans;
155  }
156
157  public static long getLastGcDuration(ObjectName gcCollector) {
158    long lastGcDuration = 0;
159    Object lastGcInfo = getValueFromMBean(gcCollector, "LastGcInfo");
160    if (lastGcInfo != null && lastGcInfo instanceof CompositeData) {
161      CompositeData cds = (CompositeData) lastGcInfo;
162      lastGcDuration = (long) cds.get("duration");
163    }
164    return lastGcDuration;
165  }
166
167  public static List<MemoryPoolMXBean> getMemoryPools() {
168    List<MemoryPoolMXBean> mPools = ManagementFactory.getMemoryPoolMXBeans();
169    return mPools;
170  }
171
172  public static float calcPercentage(long a, long b) {
173    if (a == 0 || b == 0) {
174      return 0;
175    }
176    return ((float) a / (float) b) * 100;
177  }
178}