All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.icodegarden.commons.lang.metrics.Metrics Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
package io.github.icodegarden.commons.lang.metrics;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import io.github.icodegarden.commons.lang.NamedObject;
import io.github.icodegarden.commons.lang.util.SystemUtils;

/**
 * 
 * @author Fangfang.Xu
 *
 */
public class Metrics implements NamedObject, Comparable, Serializable {
	private static final long serialVersionUID = 1L;

	private String serviceName;
	private String instanceName;
	private Map dimensions = new HashMap(4, 1);
	private String desc;

	/**
	 * kryo序列化
	 */
	Metrics() {
	}

	/**
	 * 至少有1个Dimension入参
	 * 
	 * @param d          NotNull
	 * @param dimensions
	 */
	public Metrics(Dimension d, Dimension... dimensions) {
		if (d == null) {
			throw new IllegalArgumentException("param notnull must not null");
		}
		setDimension(d);
		for (Dimension dimension : dimensions) {
			setDimension(dimension);
		}
	}

	/**
	 * 
	 * @param dimensions NotEmpty
	 */
	public Metrics(List dimensions) {
		if (dimensions == null || dimensions.isEmpty()) {
			throw new IllegalArgumentException("param dimensions must not empty");
		}
		dimensions.forEach(dimension -> {
			setDimension(dimension);
		});
	}

	@Override
	public String name() {
		return getServiceName();
	}

	public void setDimension(Dimension dimension) {
		dimensions.put(dimension.getDimensionName(), dimension);
	}

	public String getServiceName() {
		return serviceName;
	}

	public void setServiceName(String serviceName) {
		this.serviceName = serviceName;
	}

	public String getInstanceName() {
		return instanceName;
	}

	public void setInstanceName(String instanceName) {
		this.instanceName = instanceName;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public Map getDimensions() {
		return dimensions;
	}

	public Dimension getDimension(DimensionName dimensionName) {
		return dimensions.get(dimensionName);
	}

	/**
	 * 线程安全
	 * 
	 * @param dimensionName
	 * @param value
	 * @return 是否确实存在该维度,存在则会变动即使used超过max
	 */
	public boolean incrementDimension(DimensionName dimensionName, double value) {
		Dimension dimension = getDimension(dimensionName);
		if (dimension != null) {
			synchronized (dimension) {
				dimension.setUsed(dimension.getUsed() + value);
			}
			return true;
		}
		return false;
	}

	/**
	 * 线程安全
	 * 
	 * @param dimensionName
	 * @param value
	 * @return 是否确实存在该维度,存在则会变动
	 */
	public boolean decrementDimension(DimensionName dimensionName, double value) {
		Dimension dimension = getDimension(dimensionName);
		if (dimension != null) {
			synchronized (dimension) {
				dimension.setUsed(dimension.getUsed() - value);
				if (dimension.getUsed() < 0) {
					dimension.setUsed(0);
				}
			}
			return true;
		}
		return false;
	}

	/**
	 * 刷新cpu、memory已使用的值
	 */
	public void refreshUsedValues() {
		Dimension cpuD = getDimension(DimensionName.Cpu);
		if (cpuD != null) {
			cpuD.setUsed(SystemUtils.getVmRuntime().getProcessCpuLoad());
		}
		Dimension memoryD = getDimension(DimensionName.Memory);
		if (memoryD != null) {
			memoryD.setUsed(SystemUtils.getVmRuntime().getJvmUsedMemory() / 1024 / 1024);
		}
	}

	/**
	 * @return 只要有一项指标使用率达到最大值,则超载
	 */
	public boolean isOverload() {
		for (Dimension dimension : dimensions.values()) {
			if (dimension.getWeight() > 0 && dimension.getUsed() >= dimension.getMax()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 超过负载的维度
	 * 
	 * @return
	 */
	public List overloadDimensions() {
		return dimensions.values().stream().filter(dimension -> dimension.getUsed() >= dimension.getMax())
				.collect(Collectors.toList());
	}

	/**
	 * 只计算instanceName
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((instanceName == null) ? 0 : instanceName.hashCode());
		return result;
	}

	/**
	 * 只比较instanceName
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Metrics other = (Metrics) obj;
		if (instanceName == null) {
			if (other.instanceName != null)
				return false;
		} else if (!instanceName.equals(other.instanceName))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "[instanceName=" + instanceName + ", dimensions=" + dimensions + "]";
	}

	public static class DimensionName implements Serializable {
		private static final long serialVersionUID = 6468102993100427298L;

		public static final DimensionName Cpu = new DimensionName("cpu");
		public static final DimensionName Memory = new DimensionName("memory");
		/**
		 * 任务负载能力
* max=job个数*weight*每秒执行频率 = 10000*1*每秒执行频率
* max由用户决定,used=累加 每个任务的weight*每秒执行频率
* 例如10000可以是: 10000个*重量1*1000ms/频率1000ms , 1000个*重量1*1000ms/频率100ms , * 2500个*2重量*1000ms/频率500ms , 20000个*5重量*1000ms/频率10000ms
*/ public static final DimensionName Jobs = new DimensionName("jobs"); private final String value; /** * kryo序列化 */ DimensionName() { value = null; } public DimensionName(String value) { this.value = value; } public String getValue() { return value; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((value == null) ? 0 : value.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DimensionName other = (DimensionName) obj; if (value == null) { if (other.value != null) return false; } else if (!value.equals(other.value)) return false; return true; } @Override public String toString() { return "DimensionName [value=" + value + "]"; } } public static class Dimension implements Serializable { private static final long serialVersionUID = 1L; private DimensionName dimensionName; private double max; private double used; private int weight; private String desc; /** * kryo序列化 */ Dimension() { } /** * weight使用默认值1 * * @param dimensionName * @param max * @param used */ public Dimension(DimensionName dimensionName, double max, double used) { this(dimensionName, max, used, 1); } /** * * @param dimensionName * @param max * @param used * @param weight 范围必须1-100 */ public Dimension(DimensionName dimensionName, double max, double used, int weight) { if (weight < 0 || weight > 100) { throw new IllegalArgumentException("weight must range [0-100]"); } this.dimensionName = dimensionName; this.max = max; this.used = used; this.weight = weight; } public DimensionName getDimensionName() { return dimensionName; } public void setDimensionName(DimensionName dimensionName) { this.dimensionName = dimensionName; } public double getMax() { return max; } public void setMax(double max) { this.max = max; } public double getUsed() { return used; } public void setUsed(double used) { this.used = used; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } @Override public String toString() { return "Dimension [dimensionName=" + dimensionName + ", max=" + max + ", used=" + used + ", weight=" + weight + ", desc=" + desc + "]"; } } /** * other == pre */ @Override public int compareTo(Metrics other) { if (other == null) { return -1; } Map thisDimensions = this.getDimensions(); Map otherDimensions = other.getDimensions(); /** * this的剩余率-other的剩余率 */ AtomicReference minus = new AtomicReference(0D); thisDimensions.forEach((thisName, thisDimension) -> { Dimension otherDimension = otherDimensions.get(thisName); // 剩余率比较 double thisRemainRate = 0; double otherRemainRate = 0; if (otherDimension == null) { thisRemainRate = (thisDimension.getMax() - thisDimension.getUsed()) / thisDimension.getMax(); thisRemainRate *= thisDimension.getWeight(); } else { thisRemainRate = (thisDimension.getMax() - thisDimension.getUsed()) / thisDimension.getMax(); thisRemainRate *= thisDimension.getWeight(); otherRemainRate = (otherDimension.getMax() - otherDimension.getUsed()) / otherDimension.getMax(); otherRemainRate *= otherDimension.getWeight(); } minus.set(minus.get() + thisRemainRate - otherRemainRate); }); if (minus.get() == 0) { return 0; } // 如果是正的,this排前面 return minus.get() > 0 ? -1 : 1; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy