Package com.linkedin.databus2.core.container.monitoring.mbean

Source Code of com.linkedin.databus2.core.container.monitoring.mbean.HttpStatisticsCollector

package com.linkedin.databus2.core.container.monitoring.mbean;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* Licensed 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.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;

import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.log4j.Logger;

import com.linkedin.databus.core.Checkpoint;
import com.linkedin.databus.core.monitoring.mbean.AbstractMonitoringMBean;
import com.linkedin.databus.core.util.ConfigApplier;
import com.linkedin.databus.core.util.ConfigBuilder;
import com.linkedin.databus.core.util.InvalidConfigException;
import com.linkedin.databus.core.util.JmxUtil;
import com.linkedin.databus.core.util.ReadWriteSyncedObject;
import com.linkedin.databus2.core.container.request.RegisterResponseEntry;

/**
* Container for all monitoring mbeans
*/
public class HttpStatisticsCollector extends ReadWriteSyncedObject
                                     implements HttpStatisticsCollectorMBean
{
  public static final String MODULE = HttpStatisticsCollector.class.getName();
  public static final Logger LOG = Logger.getLogger(MODULE);

  private final static String NO_PEER = "NONE";

  private final DbusHttpTotalStats _totalStats;
  private final HashMap<Integer, DbusHttpTotalStats> _perSourceStats;
  private final HashMap<String, DbusHttpTotalStats> _perClientStats;
  private final MBeanServer _mbeanServer;
  private final ObjectName _collectorObjName;

  private final int _id;
  private final String _name;
  private final String _perSourceNamePrefix;
  private final String _perPeerPrefix;
  private final String _curPeer;
  private final AtomicBoolean _enabled;

  public HttpStatisticsCollector(int id, String name, boolean enabled, boolean threadSafe,
                                 MBeanServer mbeanServer)
  {
    this(id, name, enabled, threadSafe, NO_PEER, mbeanServer);
  }

  private HttpStatisticsCollector(int relayId, String name, boolean enabled, boolean threadSafe,
                                  String peer, MBeanServer mbeanServer)
  {
    super(threadSafe);

    _mbeanServer = mbeanServer;
    _curPeer = peer;
    _enabled = new AtomicBoolean(enabled);
    _id = relayId;
    _name = name;
    _perSourceNamePrefix = _name + ".source.";
    _perPeerPrefix = _name + ".peer.";

    _totalStats = new DbusHttpTotalStats(_id, _name + ".total", enabled, threadSafe, null);

    _perSourceStats = new HashMap<Integer, DbusHttpTotalStats>(100);
    _perClientStats = new HashMap<String, DbusHttpTotalStats>(1000);

    ObjectName jmxName = null;
    try
    {
      Hashtable<String, String> mbeanProps = new Hashtable<String, String>(5);
      mbeanProps.put("name", _name);
      mbeanProps.put("type", HttpStatisticsCollector.class.getSimpleName());
      mbeanProps.put("relay", Integer.toString(relayId));
      jmxName = new ObjectName(AbstractMonitoringMBean.JMX_DOMAIN, mbeanProps);
    }
    catch (Exception e)
    {
      LOG.error("Error creating JMX object name", e);
    }

    _collectorObjName = jmxName;

    registerAsMBeans();
  }

  protected void registerAsMBeans()
  {
    if (null != _mbeanServer && null != _collectorObjName)
    {
      try
      {
        if (_mbeanServer.isRegistered(_collectorObjName))
        {
          LOG.warn("unregistering stale mbean: " + _collectorObjName);
          _mbeanServer.unregisterMBean(_collectorObjName);
        }

        _mbeanServer.registerMBean(this, _collectorObjName);
        _totalStats.registerAsMbean(_mbeanServer);
        if (LOG.isDebugEnabled())
        {
          LOG.debug("MBean registered " + _collectorObjName);
        }
      }
      catch (Exception e)
      {
        LOG.error("JMX registration failed", e);
      }
    }
  }

  public void unregisterMBeans()
  {
    if (null != _mbeanServer && null != _collectorObjName)
    {
      try
      {
        JmxUtil.unregisterMBeanSafely(_mbeanServer, _collectorObjName, LOG);
        _totalStats.unregisterMbean(_mbeanServer);

        for (String clientName: _perClientStats.keySet())
        {
          _perClientStats.get(clientName).unregisterMbean(_mbeanServer);
        }

        for (Integer srcId: _perSourceStats.keySet())
        {
          _perSourceStats.get(srcId).unregisterMbean(_mbeanServer);
        }
        if (LOG.isDebugEnabled())
        {
          LOG.debug("MBean unregistered " + _collectorObjName);
        }
      }
      catch (Exception e)
      {
        LOG.error("JMX deregistration failed", e);
      }
    }
  }

  /** Creates a copy */
  public HttpStatisticsCollector createForClientConnection(String client)
  {
    return new HttpStatisticsCollector(_id, _name, true, false, client, null);
  }

  @Override
  public DbusHttpTotalStats getTotalStats()
  {
    return _totalStats;
  }

  @Override
  public List<Integer> getSources()
  {
    Lock readLock = acquireReadLock();
    try
    {
      List<Integer> result = new ArrayList<Integer>(_perSourceStats.keySet());
      return result;
    }
    finally
    {
      releaseLock(readLock);
    }
  }

  @Override
  public DbusHttpTotalStats getSourceStats(int srcId)
  {
    DbusHttpTotalStats result = getOrAddPerSourceCollector(srcId, null);
    return result;
  }

  @Override
  public List<String> getPeers()
  {
    Lock readLock = acquireReadLock();
    try
    {
      ArrayList<String> result = new ArrayList<String>(_perClientStats.keySet());
      return result;
    }
    finally
    {
      releaseLock(readLock);
    }
  }

  @Override
  public DbusHttpTotalStats getPeerStats(String peer)
  {
    Lock readLock = acquireReadLock();
    try
    {
      DbusHttpTotalStats result = _perClientStats.get(peer);
      return result;
    }
    finally
    {
      releaseLock(readLock);
    }
  }

  @Override
  public void registerRegisterCall(List<RegisterResponseEntry> sources)
  {
    if (!_enabled.get()) return;

    _totalStats.registerRegisterCall(_curPeer);

    for (RegisterResponseEntry respEntry: sources)
    {
      DbusHttpTotalStats perSourceCollector =
        getOrAddPerSourceCollector((int)respEntry.getId(), null);

      perSourceCollector.registerRegisterCall(_curPeer);
    }

    if (NO_PEER != _curPeer)
    {
      DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, null);
      clientStats.registerRegisterCall(_curPeer);
    }
  }

  @Override
  public void registerSourcesCall()
  {
    if (!_enabled.get()) return;

    _totalStats.registerSourcesCall(_curPeer);

    if (NO_PEER != _curPeer)
    {
      DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, null);
      clientStats.registerSourcesCall(_curPeer);
    }
  }

  @Override
  public void registerStreamResponse(long streamCallDuration)
  {
    if (!_enabled.get()) return;

    Lock writeLock = acquireWriteLock();
    try
    {
      _totalStats.registerStreamResponse(streamCallDuration);

      if (NO_PEER != _curPeer)
      {
        DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, writeLock);
        clientStats.registerStreamResponse(streamCallDuration);
      }

      //NOTE: we don't update per-source stats because for multi-source stream calls the latency
      //is not meaningful on per-source basis
    }
    finally
    {
      releaseLock(writeLock);
    }
  }

  @Override
  public void registerStreamRequest(Checkpoint cp, Collection<Integer> sourceIds)
  {
    if (!_enabled.get()) return;

    _totalStats.registerStreamRequest(_curPeer, cp);

    Lock writeLock = acquireWriteLock();
    try
    {
      for (Integer srcId: sourceIds)
      {
        DbusHttpTotalStats curBean = getOrAddPerSourceCollector(srcId, writeLock);
        curBean.registerStreamRequest(_curPeer, cp);
      }

      if (NO_PEER != _curPeer)
      {
        DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, writeLock);
        clientStats.registerStreamRequest(_curPeer, cp);
      }
    }
    finally
    {
      releaseLock(writeLock);
    }
  }

  public void merge(HttpStatisticsCollector other)
  {
    _totalStats.mergeStats(other._totalStats);

    Lock otherReadLock = other.acquireReadLock();
    Lock writeLock = acquireWriteLock(otherReadLock);
    try
    {
      for (Integer id: other._perSourceStats.keySet())
      {
        DbusHttpTotalStats bean = other._perSourceStats.get(id);
        mergePerSource(id, bean, writeLock);
      }

      for (String peerName: other._perClientStats.keySet())
      {
        DbusHttpTotalStats bean = other._perClientStats.get(peerName);
        mergePerPeer(peerName, bean, writeLock);
      }
    }
    finally
    {
      releaseLock(writeLock);
      releaseLock(otherReadLock);
    }
  }

  @Override
  public void reset()
  {
    _totalStats.reset();

    Lock readLock = acquireReadLock();
    try
    {
      for (Integer sourceId: _perSourceStats.keySet())
      {
        DbusHttpTotalStats sourceStats = _perSourceStats.get(sourceId);
        sourceStats.reset();
      }

      for (String peer: _perClientStats.keySet())
      {
        _perClientStats.get(peer).reset();
      }
    }
    finally
    {
      releaseLock(readLock);
    }
  }

  @Override
  public boolean isEnabled()
  {
    return _enabled.get();
  }

  @Override
  public void setEnabled(boolean enabled)
  {
    _enabled.set(enabled);
  }

  private DbusHttpTotalStats getOrAddPerSourceCollector(Integer srcId, Lock writeLock)
  {
    Lock myWriteLock = null;
    if (null == writeLock) myWriteLock = acquireWriteLock();


    try
    {
      DbusHttpTotalStats data = _perSourceStats.get(srcId);
      if (null == data)
      {
        data = new DbusHttpTotalStats(_id, _perSourceNamePrefix + srcId, true, isThreadSafe(), null);
        _perSourceStats.put(srcId, data);

        if (null != _mbeanServer)
        {
          data.registerAsMbean(_mbeanServer);
        }
      }

      return data;
    }
    finally
    {
      releaseLock(myWriteLock);
    }
  }

  private DbusHttpTotalStats getOrAddPerPeerCollector(String client, Lock writeLock)
  {
    Lock myWriteLock = null;
    if (null == writeLock) myWriteLock = acquireWriteLock();
    try
    {
      DbusHttpTotalStats clientStats = _perClientStats.get(client);
      if (null == clientStats)
      {
        clientStats = new DbusHttpTotalStats(_id, _perPeerPrefix + client, true, isThreadSafe(), null);
        _perClientStats.put(client, clientStats);

        if (null != _mbeanServer)
        {
          clientStats.registerAsMbean(_mbeanServer);
        }
      }

      return clientStats;
    }
    finally
    {
      releaseLock(myWriteLock);
    }
  }


  private void mergePerSource(Integer srcId, DbusHttpTotalStats other, Lock writeLock)
  {
    DbusHttpTotalStats curBean = getOrAddPerSourceCollector(srcId, writeLock);
    curBean.mergeStats(other);
  }

  private void mergePerPeer(String peer, DbusHttpTotalStats other, Lock writeLock)
  {
    DbusHttpTotalStats curBean = getOrAddPerPeerCollector(peer, writeLock);
    curBean.mergeStats(other);
  }


  public class RuntimeConfig implements ConfigApplier<RuntimeConfig>
  {
    private final boolean _enabled;

    public RuntimeConfig(boolean enabled)
    {
      _enabled = enabled;
    }

    /** A flag if the statistics collector is enabled and it will update the stats counters  */
    public boolean isEnabled()
    {
      return _enabled;
    }

    @Override
    public void applyNewConfig(RuntimeConfig oldConfig)
    {
      HttpStatisticsCollector.this.setEnabled(this.isEnabled());
    }

    @Override
    public boolean equals(Object other)
    {
      if (null == other || !(other instanceof RuntimeConfig)) return false;
      return equalsConfig((RuntimeConfig)other);
    }

    @Override
    public boolean equalsConfig(RuntimeConfig otherConfig)
    {
      if (null == otherConfig) return false;
      return isEnabled() == otherConfig.isEnabled();
    }

    @Override
    public int hashCode()
    {
      return _enabled ? 0 : 1;
    }
  }

  public static class RuntimeConfigBuilder implements ConfigBuilder<RuntimeConfig>
  {
    private boolean _enabled = true;
    private HttpStatisticsCollector _managedInstance = null;

    public RuntimeConfigBuilder()
    {
      super();
    }

    public boolean isEnabled()
    {
      return _enabled;
    }

    public void setEnabled(boolean enabled)
    {
      _enabled = enabled;
    }

    @Override
    public RuntimeConfig build() throws InvalidConfigException
    {
      if (null != _managedInstance) return _managedInstance.new RuntimeConfig(_enabled);
      throw new InvalidConfigException("No ContainerStatisticsCollector instance assigned");
    }

    public HttpStatisticsCollector getManagedInstance()
    {
      return _managedInstance;
    }

    public void setManagedInstance(HttpStatisticsCollector managedInstance)
    {
      _managedInstance = managedInstance;
    }

  }

  public static class StaticConfig
  {
    private final RuntimeConfigBuilder _runtime;
    private final HttpStatisticsCollector _existingStatsCollector;

    public StaticConfig(RuntimeConfigBuilder runtime, HttpStatisticsCollector existingStatsCollector)
    {
      _runtime = runtime;
      _existingStatsCollector = existingStatsCollector;
    }

    /** Runtime configuration */
    public RuntimeConfigBuilder getRuntime()
    {
      return _runtime;
    }

    public HttpStatisticsCollector getExistingStatsCollector()
    {
      return _existingStatsCollector;
    }
  }

  public static class Config implements ConfigBuilder<StaticConfig>
  {
    private final RuntimeConfigBuilder _runtime;
    private HttpStatisticsCollector _existingStatsCollector = null;

    public Config()
    {
      super();
      _runtime = new RuntimeConfigBuilder();
    }

    public RuntimeConfigBuilder getRuntime()
    {
      return _runtime;
    }

    public HttpStatisticsCollector getExisting()
    {
      return _existingStatsCollector;
    }

    public void setExisting(HttpStatisticsCollector existingStatsCollector)
    {
      _existingStatsCollector = existingStatsCollector;
    }

    @Override
    public StaticConfig build() throws InvalidConfigException
    {
      return new StaticConfig(_runtime, _existingStatsCollector);
    }

  }

  @Override
  public String getName()
  {
    return _name;
  }

  @Override
  public void registerInvalidStreamRequest()
  {
    if (!_enabled.get()) return;

    _totalStats.registerInvalidStreamRequest(_curPeer);

    Lock writeLock = acquireWriteLock();
    try
    {

      if (NO_PEER != _curPeer)
      {
        DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, writeLock);
        clientStats.registerInvalidStreamRequest(_curPeer);
      }
    }
    finally
    {
      releaseLock(writeLock);
    }

  }

  @Override
  public void registerScnNotFoundStreamResponse()
  {
    if (!_enabled.get()) return;

    _totalStats.registerScnNotFoundStreamResponse(_curPeer);

    Lock writeLock = acquireWriteLock();
    try
    {

      if (NO_PEER != _curPeer)
      {
        DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, writeLock);
        clientStats.registerScnNotFoundStreamResponse(_curPeer);
      }
    }
    finally
    {
      releaseLock(writeLock);
    }

  }

  @Override
  public void registerInvalidSourceRequest()
  {
    if (!_enabled.get()) return;

    _totalStats.registerInvalidSourceRequest(_curPeer);

    Lock writeLock = acquireWriteLock();
    try
    {

      if (NO_PEER != _curPeer)
      {
        DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, writeLock);
        clientStats.registerInvalidSourceRequest(_curPeer);
      }
    }
    finally
    {
      releaseLock(writeLock);
    }

  }

  @Override
  public void registerInvalidRegisterCall()
  {
    if (!_enabled.get()) return;

    _totalStats.registerInvalidRegisterCall(_curPeer);

    Lock writeLock = acquireWriteLock();
    try
    {

      if (NO_PEER != _curPeer)
      {
        DbusHttpTotalStats clientStats = getOrAddPerPeerCollector(_curPeer, writeLock);
        clientStats.registerInvalidRegisterCall(_curPeer);
      }
    }
    finally
    {
      releaseLock(writeLock);
    }

  }

  @Override
  public void registerMastershipStatus(int i)
  {
    //only global stats make sense;
    _totalStats.registerMastershipStatus(i);
  }

}
TOP

Related Classes of com.linkedin.databus2.core.container.monitoring.mbean.HttpStatisticsCollector

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.