| package org.apache.helix.monitoring.mbeans; |
| |
| /* |
| * 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.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import javax.management.JMException; |
| import javax.management.MalformedObjectNameException; |
| import javax.management.ObjectName; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Lists; |
| import org.apache.helix.HelixDefinedState; |
| import org.apache.helix.model.Partition; |
| import org.apache.helix.model.StateModelDefinition; |
| import org.apache.helix.monitoring.mbeans.dynamicMBeans.DynamicMBeanProvider; |
| import org.apache.helix.monitoring.mbeans.dynamicMBeans.DynamicMetric; |
| import org.apache.helix.monitoring.mbeans.dynamicMBeans.SimpleDynamicMetric; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class PerInstanceResourceMonitor extends DynamicMBeanProvider { |
| private static final Logger LOG = LoggerFactory.getLogger(PerInstanceResourceMonitor.class); |
| private static final String MBEAN_DESCRIPTION = "Per Instance Resource Monitor"; |
| |
| public static class BeanName { |
| private final String _instanceName; |
| private final String _resourceName; |
| private final String _clusterName; |
| |
| public BeanName(String clusterName, String instanceName, String resourceName) { |
| if (clusterName == null || instanceName == null || resourceName == null) { |
| throw new NullPointerException( |
| "Illegal beanName. clusterName: " + clusterName + ", instanceName: " + instanceName |
| + ", resourceName: " + resourceName); |
| } |
| _clusterName = clusterName; |
| _instanceName = instanceName; |
| _resourceName = resourceName; |
| } |
| |
| public String instanceName() { |
| return _instanceName; |
| } |
| |
| public String resourceName() { |
| return _resourceName; |
| } |
| |
| public ObjectName objectName() { |
| try { |
| return new ObjectName(String.format("%s:%s", MonitorDomainNames.ClusterStatus.name(), |
| new BeanName(_clusterName, _instanceName, _resourceName).toString())); |
| } catch (MalformedObjectNameException e) { |
| LOG.error("Failed to create object name for cluster: {}, instance: {}, resource: {}.", |
| _clusterName, _instanceName, _resourceName); |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj == null || !(obj instanceof BeanName)) { |
| return false; |
| } |
| |
| BeanName that = (BeanName) obj; |
| return _clusterName.equals(that._clusterName) && _instanceName.equals(that._instanceName) |
| && _resourceName.equals(that._resourceName); |
| } |
| |
| @Override |
| public int hashCode() { |
| return toString().hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return String.format("%s=%s,%s=%s,%s=%s", ClusterStatusMonitor.CLUSTER_DN_KEY, _clusterName, |
| ClusterStatusMonitor.INSTANCE_DN_KEY, _instanceName, ClusterStatusMonitor.RESOURCE_DN_KEY, |
| _resourceName); |
| } |
| } |
| |
| private final String _clusterName; |
| private List<String> _tags; |
| private final String _participantName; |
| private final String _resourceName; |
| private SimpleDynamicMetric<Long> _partitions; |
| |
| public PerInstanceResourceMonitor(String clusterName, String participantName, |
| String resourceName) { |
| _clusterName = clusterName; |
| _tags = ImmutableList.of(ClusterStatusMonitor.DEFAULT_TAG); |
| _participantName = participantName; |
| _resourceName = resourceName; |
| _partitions = new SimpleDynamicMetric("PartitionGauge", 0L); |
| } |
| |
| @Override |
| public String getSensorName() { |
| return Joiner.on('.').join(ImmutableList |
| .of(ClusterStatusMonitor.PARTICIPANT_STATUS_KEY, _clusterName, serializedTags(), |
| _participantName, _resourceName)).toString(); |
| } |
| |
| private String serializedTags() { |
| return Joiner.on('|').skipNulls().join(_tags).toString(); |
| } |
| |
| public String getInstanceName() { |
| return _participantName; |
| } |
| |
| public String getResourceName() { |
| return _resourceName; |
| } |
| |
| /** |
| * Update per-instance resource bean |
| * @param stateMap partition->state |
| * @tags tags instance tags |
| * @param stateModelDef |
| */ |
| public synchronized void update(Map<Partition, String> stateMap, Set<String> tags, |
| StateModelDefinition stateModelDef) { |
| if (tags == null || tags.isEmpty()) { |
| _tags = ImmutableList.of(ClusterStatusMonitor.DEFAULT_TAG); |
| } else { |
| _tags = Lists.newArrayList(tags); |
| Collections.sort(_tags); |
| } |
| |
| int cnt = 0; |
| for (String state : stateMap.values()) { |
| // Skip DROPPED and initial state (e.g. OFFLINE) |
| if (state.equalsIgnoreCase(HelixDefinedState.DROPPED.name()) || state |
| .equalsIgnoreCase(stateModelDef.getInitialState())) { |
| continue; |
| } |
| cnt++; |
| } |
| _partitions.updateValue(Long.valueOf(cnt)); |
| } |
| |
| @Override |
| public DynamicMBeanProvider register() throws JMException { |
| List<DynamicMetric<?, ?>> attributeList = new ArrayList<>(); |
| attributeList.add(_partitions); |
| doRegister(attributeList, MBEAN_DESCRIPTION, |
| new BeanName(_clusterName, _participantName, _resourceName).objectName()); |
| return this; |
| } |
| } |