/* * 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. */ package org.apache.hadoop.chukwa.extraction.demux.processor.mapper; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.hadoop.chukwa.extraction.engine.ChukwaRecord; import org.apache.hadoop.chukwa.extraction.engine.ChukwaRecordKey; import org.apache.hadoop.mapred.OutputCollector; import org.apache.hadoop.mapred.Reporter; import org.apache.log4j.Logger; public class Sar extends AbstractProcessor { static Logger log = Logger.getLogger(Sar.class); public final String recordType = this.getClass().getName(); private static String regex = "([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}) (.*?) (.*?): (.*?) \\((.*?)\\)"; private static Pattern p = null; private Matcher matcher = null; private SimpleDateFormat sdf = null; public Sar() { // TODO move that to config sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); p = Pattern.compile(regex); } @Override protected void parse(String recordEntry, OutputCollector<ChukwaRecordKey, ChukwaRecord> output, Reporter reporter) throws Throwable { log.debug("Sar record: [" + recordEntry + "] type[" + chunk.getDataType() + "]"); int i = 0; // String logLevel = null; // String className = null; matcher = p.matcher(recordEntry); while (matcher.find()) { log.debug("Sar Processor Matches"); try { Date d = sdf.parse(matcher.group(1).trim()); // logLevel = matcher.group(2); // className = matcher.group(3); // TODO create a more specific key structure // part of ChukwaArchiveKey + record index if needed key.setKey("" + d.getTime()); String[] lines = recordEntry.split("\n"); String[] headers = null; while (i < (lines.length - 1) && lines[i + 1].indexOf("Average:") < 0) { // Skip to the average lines log.debug("skip:" + lines[i]); i++; } while (i < lines.length) { ChukwaRecord record = null; if (lines[i].equals("")) { i++; headers = parseHeader(lines[i]); i++; } String data[] = parseData(lines[i]); // FIXME please validate this if (headers[1].equals("IFACE") && headers[2].equals("rxpck/s")) { log.debug("Matched Sar-Network"); record = new ChukwaRecord(); key = new ChukwaRecordKey(); this.buildGenericRecord(record, null, d.getTime(), "SystemMetrics"); } else if (headers[1].equals("IFACE") && headers[2].equals("rxerr/s")) { log.debug("Matched Sar-Network"); record = new ChukwaRecord(); key = new ChukwaRecordKey(); this.buildGenericRecord(record, null, d.getTime(), "SystemMetrics"); } else if (headers[1].equals("kbmemfree")) { log.debug("Matched Sar-Memory"); record = new ChukwaRecord(); key = new ChukwaRecordKey(); this.buildGenericRecord(record, null, d.getTime(), "SystemMetrics"); } else if (headers[1].equals("totsck")) { log.debug("Matched Sar-NetworkSockets"); record = new ChukwaRecord(); key = new ChukwaRecordKey(); this.buildGenericRecord(record, null, d.getTime(), "SystemMetrics"); } else if (headers[1].equals("runq-sz")) { log.debug("Matched Sar-LoadAverage"); record = new ChukwaRecord(); key = new ChukwaRecordKey(); this.buildGenericRecord(record, null, d.getTime(), "SystemMetrics"); } else { log.debug("No match:" + headers[1] + " " + headers[2]); } if (record != null) { int j = 0; log.debug("Data Length: " + data.length); while (j < data.length) { log.debug("header:" + headers[j] + " data:" + data[j]); //special case code to work around peculiar versions of Sar if(headers[j].equals("rxkB/s")) { record.add("rxbyt/s", Double.toString(Double.parseDouble(data[j]) * 1000)); } else if(headers[j].equals("txkB/s")){ record.add("txbyt/s", Double.toString(Double.parseDouble(data[j]) * 1000)); } else if (!headers[j].equals("Average:")) { //common case record.add(headers[j], data[j]); } j++; } output.collect(key, record); } i++; } // End of parsing } catch (Exception e) { e.printStackTrace(); throw e; } } } public String[] parseHeader(String header) { String[] headers = header.split("\\s+"); return headers; } public String[] parseData(String dataLine) { String[] data = dataLine.split("\\s+"); return data; } public String getDataType() { return recordType; } }