package com.sohu.cache.server.data; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang.math.NumberUtils; /** * io读写情况 */ public class Disk implements LineParser{ public static final String FLAG = "DISK"; public static final Pattern PATTERN = Pattern.compile("^BBBP,[0-9]+,/bin/df-m,"); public static final Pattern SUBPARTITION_PATTERN = Pattern.compile("[0-9]+$"); //包括总的状况及各个分区的状况 private Map<DiskUsageType, List<Usage>> diskMap = new HashMap<Disk.DiskUsageType, List<Usage>>(); /** * line format: * DISKBUSY,Disk %Busy iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKREAD,Disk Read KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKWRITE,Disk Write KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKXFER,Disk transfers per second iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKBSIZE,Disk Block Size iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKBUSY,T0001,0.0,0.0,0.0,0.0 * DISKREAD,T0001,0.0,0.0,0.0,0.0 * DISKWRITE,T0001,0.0,0.0,0.0,0.0 * DISKXFER,T0001,0.0,0.0,0.0,0.0 * DISKBSIZE,T0001,0.0,0.0,0.0,0.0 * BBBP,173,/bin/df-m,"ddev/xvda1 20158 16018 3117 84% /" */ public void parse(String line, String timeKey) throws Exception{ if(line.startsWith(FLAG)) { String[] items = line.split(","); if(!items[1].equals(timeKey)) { DiskUsageType type = DiskUsageType.getType(items[0]); if(type == null) { return; } List<Usage> list = diskMap.get(type); if(list == null) { list = new ArrayList<Usage>(); diskMap.put(type, list); } for(int i = 2; i < items.length; ++i) { Usage usage = new Usage(); usage.setDiskUsageTyp(type); usage.setName(items[i]); list.add(usage); } } else { DiskUsageType type = DiskUsageType.getType(items[0]); if(type == null) { return; } List<Usage> list = diskMap.get(type); if(list == null) { return; } for(int i = 2; i < items.length; ++i) { float value = NumberUtils.toFloat(items[i]); if(value > 0) { list.get(i-2).setValue(value); } } } } else if(PATTERN.matcher(line).find()) { String[] tmp = line.split(",\""); if(tmp.length > 0) { String[] item = tmp[tmp.length - 1].split("\\s+"); if(item.length != 6 || !item[4].contains("%")) { return; } List<Usage> list = diskMap.get(DiskUsageType.busy); String[] tp = item[0].split("/"); String mount = tp[tp.length - 1]; for(Usage usage : list) { if(usage.getName().equals(mount)) { List<Usage> spaceList = diskMap.get(DiskUsageType.space); if(spaceList == null) { spaceList = new ArrayList<Usage>(); diskMap.put(DiskUsageType.space, spaceList); } Usage spaceUsage = new Usage(); spaceUsage.setDiskUsageTyp(DiskUsageType.space); spaceUsage.setName(usage.getName()); spaceUsage.setValue(NumberUtils.toFloat(item[4].split("%")[0])); spaceList.add(spaceUsage); } } } } } public Map<DiskUsageType, List<Usage>> getDiskMap() { return diskMap; } public float getRead() { List<Usage> usageList = diskMap.get(DiskUsageType.read); return getUsage(usageList); } public float getWrite() { List<Usage> usageList = diskMap.get(DiskUsageType.write); return getUsage(usageList); } public float getIops() { List<Usage> usageList = diskMap.get(DiskUsageType.transfer); return getUsage(usageList); } public float getBusy() { List<Usage> usageList = diskMap.get(DiskUsageType.busy); return getUsage(usageList); } public String getExt() { StringBuilder sb = new StringBuilder(); for(DiskUsageType type : diskMap.keySet()) { if(DiskUsageType.space == type) { continue; } sb.append(type.getValue()); sb.append("="); List<Usage> usageList = diskMap.get(type); for(Usage use : usageList) { sb.append(use.getName()); sb.append(":"); sb.append(use.getValue()); sb.append(","); } sb.append(";"); } return sb.toString(); } public String getSpace() { StringBuilder sb = new StringBuilder(); List<Usage> usageList = diskMap.get(DiskUsageType.space); if(usageList == null) { return sb.toString(); } for(Usage use : usageList) { sb.append(use.getName()); sb.append(":"); sb.append(use.getValue()); sb.append(","); } return sb.toString(); } private float getUsage(List<Usage> usageList) { float usage = 0; if(usageList != null) { for(Usage u : usageList) { if(!SUBPARTITION_PATTERN.matcher(u.getName()).find()) { usage += u.getValue(); } } } return usage; } @Override public String toString() { return "Disk [diskMap=" + diskMap + "]"; } /** * 使用率 */ class Usage{ //分区名字 private String name; //使用率类型 private DiskUsageType diskUsageType; //使用率 private float value; public DiskUsageType getDiskUsageType() { return diskUsageType; } public void setDiskUsageTyp(DiskUsageType diskUsageType) { this.diskUsageType = diskUsageType; } public float getValue() { return value; } public void setValue(float value) { this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Usage [name=" + name + ", diskUsageType=" + diskUsageType + ", value=" + value + "]"; } } /** * 使用率类型 */ enum DiskUsageType{ //繁忙程度 busy("DISKBUSY"), //读 read("DISKREAD"), //写 write("DISKWRITE"), //io次数 transfer("DISKXFER"), //空间使用率 space("df"), ; private String value; private DiskUsageType(String value) { this.value = value; } public String getValue() { return value; } public static DiskUsageType getType(String type) { for(DiskUsageType dut : DiskUsageType.values()) { if(dut.getValue().equals(type)) { return dut; } } return null; } } }