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 com.fasterxml.jackson.core.JsonProcessingException; 021import com.fasterxml.jackson.databind.JsonNode; 022import com.fasterxml.jackson.databind.ObjectMapper; 023import java.beans.IntrospectionException; 024import java.io.IOException; 025import java.io.PrintWriter; 026import java.io.StringWriter; 027import java.lang.management.GarbageCollectorMXBean; 028import java.lang.management.ManagementFactory; 029import java.lang.management.MemoryPoolMXBean; 030import java.lang.management.RuntimeMXBean; 031import java.util.Hashtable; 032import java.util.List; 033import java.util.Set; 034import javax.management.InstanceNotFoundException; 035import javax.management.MBeanAttributeInfo; 036import javax.management.MBeanInfo; 037import javax.management.MBeanServer; 038import javax.management.MalformedObjectNameException; 039import javax.management.ObjectName; 040import javax.management.ReflectionException; 041import javax.management.openmbean.CompositeData; 042import org.apache.yetus.audience.InterfaceAudience; 043import org.slf4j.Logger; 044import org.slf4j.LoggerFactory; 045 046@InterfaceAudience.Private 047public final class JSONMetricUtil { 048 049 private static final Logger LOG = LoggerFactory.getLogger(JSONMetricUtil.class); 050 051 private static MBeanServer mbServer = ManagementFactory.getPlatformMBeanServer(); 052 //MBeans ObjectName domain names 053 public static final String JAVA_LANG_DOMAIN = "java.lang"; 054 public static final String JAVA_NIO_DOMAIN = "java.nio"; 055 public static final String SUN_MGMT_DOMAIN = "com.sun.management"; 056 public static final String HADOOP_DOMAIN = "Hadoop"; 057 058 //MBeans ObjectName properties key names 059 public static final String TYPE_KEY = "type"; 060 public static final String NAME_KEY = "name"; 061 public static final String SERVICE_KEY = "service"; 062 public static final String SUBSYSTEM_KEY = "sub"; 063 064/** 065 * Utility for getting metric values. Collection of static methods intended for 066 * easier access to metric values. 067 */ 068 private JSONMetricUtil() { 069 // Not to be called 070 } 071 072 public static MBeanAttributeInfo[] getMBeanAttributeInfo(ObjectName bean) 073 throws IntrospectionException, InstanceNotFoundException, ReflectionException, 074 IntrospectionException, javax.management.IntrospectionException { 075 MBeanInfo mbinfo = mbServer.getMBeanInfo(bean); 076 return mbinfo.getAttributes(); 077 } 078 079 public static Object getValueFromMBean(ObjectName bean, String attribute) { 080 Object value = null; 081 try { 082 value = mbServer.getAttribute(bean, attribute); 083 } 084 catch(Exception e) { 085 LOG.error("Unable to get value from MBean= "+ bean.toString() + 086 "for attribute=" + attribute + " " + e.getMessage()); 087 } 088 return value; 089 } 090 091 /** 092 * Returns a subset of mbeans defined by qry. 093 * Modeled after DumpRegionServerMetrics#dumpMetrics. 094 * Example: String qry= "java.lang:type=Memory" 095 * @throws MalformedObjectNameException if json have bad format 096 * @throws IOException / 097 * @return String representation of json array. 098 */ 099 public static String dumpBeanToString(String qry) throws MalformedObjectNameException, 100 IOException { 101 StringWriter sw = new StringWriter(1024 * 100); // Guess this size 102 try (PrintWriter writer = new PrintWriter(sw)) { 103 JSONBean dumper = new JSONBean(); 104 try (JSONBean.Writer jsonBeanWriter = dumper.open(writer)) { 105 MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); 106 jsonBeanWriter.write(mbeanServer, 107 new ObjectName(qry), null, false); 108 } 109 } 110 sw.close(); 111 return sw.toString(); 112 } 113 114 public static JsonNode mappStringToJsonNode(String jsonString) 115 throws JsonProcessingException, IOException { 116 ObjectMapper mapper = new ObjectMapper(); 117 JsonNode node = mapper.readTree(jsonString); 118 return node; 119 } 120 121 122 public static JsonNode searchJson(JsonNode tree, String searchKey) 123 throws JsonProcessingException, IOException { 124 if (tree == null) { 125 return null; 126 } 127 if(tree.has(searchKey)) { 128 return tree.get(searchKey); 129 } 130 if(tree.isContainerNode()) { 131 for(JsonNode branch: tree) { 132 JsonNode branchResult = searchJson(branch, searchKey); 133 if (branchResult != null && !branchResult.isMissingNode()) { 134 return branchResult; 135 } 136 } 137 } 138 return null; 139 } 140 141 /** 142 * Method for building hashtable used for constructing ObjectName. 143 * Mapping is done with arrays indices 144 * @param keys Hashtable keys 145 * @param values Hashtable values 146 * @return Hashtable or null if arrays are empty * or have different number of elements 147 */ 148 public static Hashtable<String, String> buldKeyValueTable(String[] keys, String[] values) { 149 if (keys.length != values.length) { 150 LOG.error("keys and values arrays must be same size"); 151 return null; 152 } 153 if (keys.length == 0 || values.length == 0) { 154 LOG.error("keys and values arrays can not be empty;"); 155 return null; 156 } 157 Hashtable<String, String> table = new Hashtable<String, String>(); 158 for(int i = 0; i < keys.length; i++) { 159 table.put(keys[i], values[i]); 160 } 161 return table; 162 } 163 164 public static ObjectName buildObjectName(String pattern) throws MalformedObjectNameException { 165 return new ObjectName(pattern); 166 } 167 168 public static ObjectName buildObjectName(String domain, Hashtable<String, String> keyValueTable) 169 throws MalformedObjectNameException { 170 return new ObjectName(domain, keyValueTable); 171 } 172 173 public static Set<ObjectName> getRegistredMBeans(ObjectName name, MBeanServer mbs) { 174 return mbs.queryNames(name, null); 175 } 176 177 public static String getProcessPID() { 178 return ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; 179 } 180 181 public static String getCommmand() throws MalformedObjectNameException, 182 IOException { 183 RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); 184 return runtimeBean.getSystemProperties().get("sun.java.command"); 185 } 186 187 public static List<GarbageCollectorMXBean> getGcCollectorBeans() { 188 List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans(); 189 return gcBeans; 190 } 191 192 public static long getLastGcDuration(ObjectName gcCollector) { 193 long lastGcDuration = 0; 194 Object lastGcInfo = getValueFromMBean(gcCollector, "LastGcInfo"); 195 if (lastGcInfo != null && lastGcInfo instanceof CompositeData) { 196 CompositeData cds = (CompositeData)lastGcInfo; 197 lastGcDuration = (long) cds.get("duration"); 198 } 199 return lastGcDuration; 200 } 201 202 public static List<MemoryPoolMXBean> getMemoryPools() { 203 List<MemoryPoolMXBean> mPools = ManagementFactory.getMemoryPoolMXBeans(); 204 return mPools; 205 } 206 207 public static float calcPercentage(long a, long b) { 208 if (a == 0 || b == 0) { 209 return 0; 210 } 211 return ((float)a / (float)b) *100; 212 } 213}