package com.intrbiz.bergamot.nagios.model; import java.io.IOException; import java.nio.CharBuffer; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.intrbiz.gerald.polyakov.Reading; import com.intrbiz.gerald.polyakov.gauge.DoubleGaugeReading; public class NagiosPerfData { private static final Pattern VALUE_UOM_PATTERN = Pattern.compile("\\A([-0-9.]+)(%|[num]?s|[KkMGT]i?[Bb]|c)?\\z"); private String label; private String value; private String unit; private String warning; private String critical; private String min; private String max; public NagiosPerfData() { super(); } public NagiosPerfData(String label, String value, String unit, String warning, String critical, String min, String max) { super(); this.label = label; this.value = value; this.unit = unit; this.warning = warning; this.critical = critical; this.min = min; this.max = max; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getUnit() { return unit; } public void setUnit(String unit) { this.unit = unit; } public String getWarning() { return warning; } public void setWarning(String warning) { this.warning = warning; } public String getCritical() { return critical; } public void setCritical(String critical) { this.critical = critical; } public String getMin() { return min; } public void setMin(String min) { this.min = min; } public String getMax() { return max; } public void setMax(String max) { this.max = max; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.label).append("="); sb.append(this.value); if (this.unit != null) sb.append(this.unit); if (this.warning != null) sb.append(";").append(this.warning); if (this.critical != null) sb.append(";").append(this.critical); if (this.min != null) sb.append(";").append(this.min); if (this.max != null) sb.append(";").append(this.max); return sb.toString(); } public Reading toReading() { if (this.unit == null || this.unit.length() == 0) { // this is a dimension-less measure, as such default to double gauge DoubleGaugeReading reading = new DoubleGaugeReading(); reading.setName(this.label); reading.setValue(Double.parseDouble(this.value)); if (this.warning != null && this.warning.length() > 0) reading.setWarning(Double.parseDouble(this.warning)); if (this.critical != null && this.critical.length() > 0) reading.setCritical(Double.parseDouble(this.critical)); if (this.min != null && this.min.length() > 0) reading.setMin(Double.parseDouble(this.min)); if (this.max != null && this.max.length() > 0) reading.setMax(Double.parseDouble(this.max)); return reading; } else { // look at the unit to better select the data type if ("B".equals(unit) || "kB".equals(unit) || "KB".equals(unit) || "MB".equals(unit) || "GB".equals(unit) || "TB".equals(unit) || "c".equals(unit)) { DoubleGaugeReading reading = new DoubleGaugeReading(); reading.setName(this.label); reading.setUnit(this.unit); reading.setValue(Double.parseDouble(this.value)); if (this.warning != null && this.warning.length() > 0) reading.setWarning(Double.parseDouble(this.warning)); if (this.critical != null && this.critical.length() > 0) reading.setCritical(Double.parseDouble(this.critical)); if (this.min != null && this.min.length() > 0) reading.setMin(Double.parseDouble(this.min)); if (this.max != null && this.max.length() > 0) reading.setMax(Double.parseDouble(this.max)); return reading; } else if ("s".equals(unit) || "ms".equals(unit) || "us".equals(unit) || "ns".equals(unit) || "%".equals(unit)) { DoubleGaugeReading reading = new DoubleGaugeReading(); reading.setName(this.label); reading.setUnit(this.unit); reading.setValue(Double.parseDouble(this.value)); if (this.warning != null && this.warning.length() > 0) reading.setWarning(Double.parseDouble(this.warning)); if (this.critical != null && this.critical.length() > 0) reading.setCritical(Double.parseDouble(this.critical)); if (this.min != null && this.min.length() > 0) reading.setMin(Double.parseDouble(this.min)); if (this.max != null && this.max.length() > 0) reading.setMax(Double.parseDouble(this.max)); return reading; } } return null; } // helpers public static List<NagiosPerfData> parsePerfData(String perfData) throws IOException { List<NagiosPerfData> perfs = new LinkedList<NagiosPerfData>(); // parse sample: load1=0.490;15.000;30.000;0; load5=0.760;10.000;25.000;0; load15=0.850;5.000;20.000;0; CharBuffer buffer = CharBuffer.wrap(perfData.toCharArray()); while (buffer.hasRemaining()) { // read the label skipWhitespace(buffer); String label = readLabel(buffer); String valueString = readValue(buffer); String[] values = valueString.split(";"); // the values String valueUOM = values.length > 0 ? values[0] : null; String warn = values.length > 1 ? values[1] : null; String crit = values.length > 2 ? values[2] : null; String min = values.length > 3 ? values[3] : null; String max = values.length > 4 ? values[4] : null; // parse the value and unit Matcher matcher = VALUE_UOM_PATTERN.matcher(valueUOM); if (matcher.matches()) { String value = matcher.group(1); String unit = matcher.group(2); // yay! perfs.add(new NagiosPerfData(label, value, unit, warn, crit, min, max)); } else { throw new IOException("Malformed perfdata value: " + valueUOM); } } // return perfs; } public static void skipWhitespace(CharBuffer buffer) { while (buffer.hasRemaining()) { if (! Character.isWhitespace(buffer.get())) { buffer.position(buffer.position() - 1); break; } } } public static String readValue(CharBuffer buffer) throws IOException { StringBuilder value = new StringBuilder(); char c; while (buffer.hasRemaining()) { c = buffer.get(); if (Character.isWhitespace(c)) break; value.append(c); } return value.toString(); } public static String readLabel(CharBuffer buffer) throws IOException { StringBuilder label = new StringBuilder(); char start = buffer.get(); if (start == '\'' || start == '"') { char c; while (buffer.hasRemaining()) { c = buffer.get(); if (c == start) { if (buffer.hasRemaining()) { char n = buffer.get(); if (n == start) { label.append(c); } else if (n == '=') { break; } else { throw new IOException("Reached end of label, was expecting: ="); } } } else { label.append(c); } } } else { label.append(start); char c; while ((c = buffer.get()) != '=' && buffer.hasRemaining()) { label.append(c); } } return label.toString(); } }