/* * 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.io.IOException; import java.net.InetAddress; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.hadoop.chukwa.extraction.engine.Record; 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 ClientTraceProcessor extends AbstractProcessor { private static final String recordType = "ClientTrace"; private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); private final Matcher kvMatcher; private final Matcher idMatcher; private final Matcher ipMatcher; // extract date, source private final Pattern idPattern = Pattern.compile("^(.{23}).*clienttrace.*"); // extract "key: value" pairs private final Pattern kvPattern = Pattern.compile("\\s+(\\w+):\\s+([^,]+)"); private final Pattern ipPattern = Pattern.compile("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"); public ClientTraceProcessor() { super(); kvMatcher = kvPattern.matcher(""); idMatcher = idPattern.matcher(""); ipMatcher = ipPattern.matcher(""); } public enum Locality { LOCAL("local"), INTRA("intra_rack"), INTER("inter_rack"); String lbl; Locality(String lbl) { this.lbl = lbl; } public String getLabel() { return lbl; } }; protected Locality getLocality(String src, String dst) throws Exception { if (null == src || null == dst) { throw new IOException("Missing src/dst"); } ipMatcher.reset(src); if (!ipMatcher.find()) { throw new IOException("Could not find src"); } byte[] srcIP = InetAddress.getByName(ipMatcher.group(0)).getAddress(); ipMatcher.reset(dst); if (!ipMatcher.find()) { throw new IOException("Could not find dst"); } byte[] dstIP = InetAddress.getByName(ipMatcher.group(0)).getAddress(); for (int i = 0; i < 4; ++i) { if (srcIP[i] != dstIP[i]) { return (3 == i && (srcIP[i] & 0xC0) == (dstIP[i] & 0xC0)) ? Locality.INTRA : Locality.INTER; } } return Locality.LOCAL; } @Override public void parse(String recordEntry, OutputCollector<ChukwaRecordKey,ChukwaRecord> output, Reporter reporter) throws Throwable { try { idMatcher.reset(recordEntry); long ms; long ms_fullresolution; if (idMatcher.find()) { ms = sdf.parse(idMatcher.group(1)).getTime(); ms_fullresolution = ms; } else { throw new IOException("Could not find date/source"); } kvMatcher.reset(recordEntry); if (!kvMatcher.find()) { throw new IOException("Failed to find record"); } ChukwaRecord rec = new ChukwaRecord(); do { rec.add(kvMatcher.group(1), kvMatcher.group(2)); } while (kvMatcher.find()); Locality loc = getLocality(rec.getValue("src"), rec.getValue("dest")); rec.add("locality", loc.getLabel()); calendar.setTimeInMillis(ms); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); ms = calendar.getTimeInMillis(); calendar.set(Calendar.MINUTE, 0); key.setKey(calendar.getTimeInMillis() + "/" + loc.getLabel() + "/" + rec.getValue("op").toLowerCase() + "/" + ms); key.setReduceType("ClientTrace"); rec.setTime(ms); rec.add(Record.tagsField, chunk.getTags()); rec.add(Record.sourceField, chunk.getSource()); rec.add(Record.applicationField, chunk.getStreamName()); rec.add("actual_time",(new Long(ms_fullresolution)).toString()); output.collect(key, rec); } catch (ParseException e) { log.warn("Unable to parse the date in DefaultProcessor [" + recordEntry + "]", e); e.printStackTrace(); throw e; } catch (IOException e) { log.warn("Unable to collect output in DefaultProcessor [" + recordEntry + "]", e); e.printStackTrace(); throw e; } } public String getDataType() { return recordType; } }