Package org.apache.helix.tools

Source Code of org.apache.helix.tools.JmxDumper$SampleTask

package org.apache.helix.tools;

/*
* 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.
*/

import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerDelegate;
import javax.management.MBeanServerNotification;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.relation.MBeanServerNotificationFilter;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.Logger;

public class JmxDumper implements NotificationListener
{
  public static final String help = "help";
  public static final String domain = "domain";
  public static final String fields = "fields";
  public static final String pattern = "pattern";
  public static final String operations = "operations";
  public static final String period = "period";
  public static final String className = "className";
  public static final String outputFile = "outputFile";
  public static final String jmxUrl = "jmxUrl";
  public static final String sampleCount = "sampleCount";
 
  private static final Logger _logger = Logger.getLogger(JmxDumper.class);
  String _domain;
  MBeanServerConnection _mbeanServer;
 
  String _beanClassName;
  String _namePattern;
  int _samplePeriod;
 
  Map<ObjectName,ObjectName> _mbeanNames = new ConcurrentHashMap<ObjectName,ObjectName>();
  Timer _timer;
 
  String _outputFileName;
 
  List<String> _outputFields = new ArrayList<String>();
  Set<String> _operations = new HashSet<String>();
  PrintWriter _outputFile;
  int _samples = 0;
  int _targetSamples = -1;
  String _jmxUrl;
 
  public JmxDumper(String jmxService,
      String domain,
      String beanClassName,
      String namePattern,
      int samplePeriod,
      List<String> fields,
      List<String> operations,
      String outputfile,
      int sampleCount
      ) throws Exception
  {
    _jmxUrl = jmxService;
    _domain = domain;
    _beanClassName = beanClassName;
    _samplePeriod = samplePeriod;
    _outputFields.addAll(fields);
    _operations.addAll(operations);
    _outputFileName = outputfile;
    _namePattern = namePattern;
    _targetSamples = sampleCount;
   
    JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + _jmxUrl + "/jmxrmi");
    JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
   
    _mbeanServer = jmxc.getMBeanServerConnection();
    MBeanServerNotificationFilter filter = new MBeanServerNotificationFilter();
    filter.enableAllObjectNames();
    _mbeanServer.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, this, filter, null);
    init();
    _timer = new Timer(true);
    _timer.scheduleAtFixedRate(new SampleTask(), _samplePeriod, _samplePeriod);
  }
 
  class SampleTask extends TimerTask
  {
    @Override
    public void run()
    {
      List<ObjectName> errorMBeans = new ArrayList<ObjectName>();
      _logger.info("Sampling " + _mbeanNames.size() + " beans");
      for(ObjectName beanName : _mbeanNames.keySet())
      {
        MBeanInfo info;
        try
        {
          info = _mbeanServer.getMBeanInfo(beanName);
        }
        catch (Exception e)
        {
          _logger.error( e.getMessage()+" removing it");
          errorMBeans.add(beanName);
          continue;
        }
        if(!info.getClassName().equals(_beanClassName))
        {
          _logger.warn("Skip: className "+info.getClassName() + " expected : "+ _beanClassName);
          continue;
        }
        StringBuffer line = new StringBuffer();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-hh:mm:ss:SSS");
        String date = dateFormat.format(new Date());
        line.append(date + " ");
        line.append(beanName.toString() + " ");
       
        MBeanAttributeInfo[] infos = info.getAttributes();
        Map<String, MBeanAttributeInfo> infoMap = new HashMap<String, MBeanAttributeInfo>();
        for(MBeanAttributeInfo infoItem : infos)
        {
          infoMap.put(infoItem.getName(), infoItem);
        }
       
        for(String outputField : _outputFields)
        {
          try
          {
            if(infoMap.containsKey(outputField))
            {
              Object mbeanAttributeValue = _mbeanServer.getAttribute(beanName, outputField);
              line.append(mbeanAttributeValue.toString() + " ");
            }
            else
            {
              _logger.warn(outputField + " not found");
              line.append("null ");
            }
          }
          catch (Exception e)
          {
            _logger.error("Error:", e);
            line.append("null ");
            continue;
          }
        }
        MBeanOperationInfo[] operations = info.getOperations();
        Map<String, MBeanOperationInfo> opeMap = new HashMap<String, MBeanOperationInfo>();
        for(MBeanOperationInfo opeItem : operations)
        {
          opeMap.put(opeItem.getName(), opeItem);
        }
       
        for(String ope : _operations)
        {
          if(opeMap.containsKey(ope))
          {
            try
            {
              _mbeanServer.invoke(beanName, ope, new Object[0], new String[0]);
              //System.out.println(ope+" invoked");
            }
            catch(Exception e)
            {
              _logger.error("Error:", e);
              continue;
            }
          }
        }
        _outputFile.println(line.toString());
        //System.out.println(line);
      }
      for(ObjectName deadBean : errorMBeans)
      {
        _mbeanNames.remove(deadBean);
      }

      _samples ++;
      //System.out.println("samples:"+_samples);
      if(_samples == _targetSamples)
      {
        synchronized(JmxDumper.this)
        {
          _logger.info(_samples + " samples done, exiting...");
          JmxDumper.this.notifyAll();
        }
      }
    }
  }
 
  void init() throws Exception
  {
    try
    {
      Set<ObjectInstance> existingInstances = _mbeanServer.queryMBeans(new ObjectName(_namePattern), null);
      _logger.info("Total " + existingInstances.size() + " mbeans matched " + _namePattern);
      for(ObjectInstance instance : existingInstances)
      {
        if(instance.getClassName().equals(_beanClassName))
        {
          _mbeanNames.put(instance.getObjectName(), instance.getObjectName());
          _logger.info("Sampling " + instance.getObjectName());
        }
      }
      FileWriter fos = new FileWriter(_outputFileName);
      System.out.println(_outputFileName);
      _outputFile = new PrintWriter(fos);
    }
    catch (Exception e)
    {
      _logger.error("fail to get all existing mbeans in " + _domain, e);
      throw e;
   
  }
  @Override
  public void handleNotification(Notification notification, Object handback)
  {
    MBeanServerNotification mbs = (MBeanServerNotification) notification;
    if(MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(mbs.getType()))
    {
      //System.out.println("Adding mbean " + mbs.getMBeanName());
      _logger.info("Adding mbean " + mbs.getMBeanName());
      if(mbs.getMBeanName().getDomain().equalsIgnoreCase(_domain))
      {
        addMBean( mbs.getMBeanName());
      }
    }
    else if(MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(mbs.getType()))
    {
      //System.out.println("Removing mbean " + mbs.getMBeanName());
      _logger.info("Removing mbean " + mbs.getMBeanName());
      if(mbs.getMBeanName().getDomain().equalsIgnoreCase(_domain))
      {
        removeMBean(mbs.getMBeanName());
      }
    }
  }
 
  private void addMBean(ObjectName beanName)
  {
    _mbeanNames.put(beanName, beanName);
  }
 
  private void removeMBean(ObjectName beanName)
  {
    _mbeanNames.remove(beanName);
  }
 
  public static int processCommandLineArgs(String[] cliArgs) throws Exception
  {
    CommandLineParser cliParser = new GnuParser();
    Options cliOptions = constructCommandLineOptions();
    CommandLine cmd = null;

    try
    {
      cmd = cliParser.parse(cliOptions, cliArgs);
    }
    catch (ParseException pe)
    {
      System.err.println("CommandLineClient: failed to parse command-line options: "
          + pe.toString());
      printUsage(cliOptions);
      System.exit(1);
    }
    boolean ret = checkOptionArgsNumber(cmd.getOptions());
    if (ret == false)
    {
      printUsage(cliOptions);
      System.exit(1);
    }
   
    String portStr = cmd.getOptionValue(jmxUrl);
    //int portVal = Integer.parseInt(portStr);
   
    String periodStr = cmd.getOptionValue(period);
    int periodVal = Integer.parseInt(periodStr);
   
    String domainStr = cmd.getOptionValue(domain);
    String classNameStr = cmd.getOptionValue(className);
    String patternStr = cmd.getOptionValue(pattern);
    String fieldsStr = cmd.getOptionValue(fields);
    String operationsStr = cmd.getOptionValue(operations);
    String resultFile = cmd.getOptionValue(outputFile);
    String sampleCountStr = cmd.getOptionValue(sampleCount, "-1");
    int sampleCount = Integer.parseInt(sampleCountStr);
   
    List<String> fields = Arrays.asList(fieldsStr.split(","));
    List<String> operations = Arrays.asList(operationsStr.split(","));
   
    JmxDumper dumper = null;
    try
    {
      dumper = new JmxDumper(portStr, domainStr, classNameStr, patternStr, periodVal, fields, operations, resultFile, sampleCount);
      synchronized(dumper)
      {
        dumper.wait();
      }
    }
    finally
    {
      if(dumper != null)
      {
        dumper.flushFile();
      }
    }
    return 0;
  }
 
  private void flushFile()
  {
    if(_outputFile != null)
    {
      _outputFile.flush();
      _outputFile.close();
    }
  }
  private static boolean checkOptionArgsNumber(Option[] options)
  {
    for (Option option : options)
    {
      int argNb = option.getArgs();
      String[] args = option.getValues();
      if (argNb == 0)
      {
        if (args != null && args.length > 0)
        {
          System.err.println(option.getArgName() + " shall have " + argNb
              + " arguments (was " + Arrays.toString(args) + ")");
          return false;
        }
      }
      else
      {
        if (args == null || args.length != argNb)
        {
          System.err.println(option.getArgName() + " shall have " + argNb
              + " arguments (was " + Arrays.toString(args) + ")");
          return false;
        }
      }
    }
    return true;
  }
 
  @SuppressWarnings("static-access")
  private static Options constructCommandLineOptions()
  {
    Option helpOption =
        OptionBuilder.withLongOpt(help)
                     .withDescription("Prints command-line options info")
                     .create();
    Option domainOption =
        OptionBuilder.withLongOpt(domain)
                     .withDescription("Domain of the JMX bean")
                     .create();

    domainOption.setArgs(1);
    domainOption.setRequired(true);
   
    Option fieldsOption =
        OptionBuilder.withLongOpt(fields)
                     .withDescription("Fields of the JMX bean to sample")
                     .create();
    fieldsOption.setArgs(1);
    fieldsOption.setRequired(false);
   
    Option operationOption =
        OptionBuilder.withLongOpt(operations)
                     .withDescription("Operation to invoke")
                     .create();
    operationOption.setArgs(1);
    operationOption.setRequired(true);
   
    Option periodOption =
        OptionBuilder.withLongOpt(period)
                     .withDescription("Sampling period in MS")
                     .create();
    periodOption.setArgs(1);
    periodOption.setRequired(false);
   
    Option classOption =
        OptionBuilder.withLongOpt(className)
                     .withDescription("Classname of the MBean")
                     .create();
    classOption.setArgs(1);
    classOption.setRequired(true);
   
    Option patternOption =
        OptionBuilder.withLongOpt(pattern)
                     .withDescription("pattern of the MBean")
                     .create();
    patternOption.setArgs(1);
    patternOption.setRequired(true);
   
    Option outputFileOption =
        OptionBuilder.withLongOpt(outputFile)
                     .withDescription("outputFileName")
                     .create();
    outputFileOption.setArgs(1);
    outputFileOption.setRequired(false);
   
    Option jmxUrlOption =
        OptionBuilder.withLongOpt(jmxUrl)
                     .withDescription("jmx port to connect to")
                     .create();
    jmxUrlOption.setArgs(1);
    jmxUrlOption.setRequired(true);
   
    Option sampleCountOption =
        OptionBuilder.withLongOpt(sampleCount)
                     .withDescription("# of samples to take")
                     .create();
    sampleCountOption.setArgs(1);
    sampleCountOption.setRequired(false);
   
    Options options = new Options();
    options.addOption(helpOption);
    options.addOption(domainOption);
    options.addOption(fieldsOption);
    options.addOption(operationOption);
    options.addOption(classOption);
    options.addOption(outputFileOption);
    options.addOption(jmxUrlOption);
    options.addOption(patternOption);
    options.addOption(periodOption);
    options.addOption(sampleCountOption);
    return options;
  }
 

  public static void printUsage(Options cliOptions)
  {
    HelpFormatter helpFormatter = new HelpFormatter();
    helpFormatter.printHelp("java " + JmxDumper.class.getName(), cliOptions);
  }
 
  public static void main(String[] args) throws Exception
  {
   /* List<String> fields = Arrays.asList(new String("AvgLatency,MaxLatency,MinLatency,PacketsReceived,PacketsSent").split(","));
    List<String> operations = Arrays.asList(new String("resetCounters").split(","));
   
    JmxDumper dumper = new JmxDumper(27961, "org.apache.zooKeeperService", "org.apache.zookeeper.server.ConnectionBean", "org.apache.ZooKeeperService:name0=*,name1=Connections,name2=*,name3=*", 1000, fields, operations, "/tmp/1.csv");
    Thread.currentThread().join();
    */
    int ret = processCommandLineArgs(args);
    System.exit(ret);
  }
}
TOP

Related Classes of org.apache.helix.tools.JmxDumper$SampleTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.