content: /*
   * 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.inputtools.log4j;
  
  /**
   * Log4JMetricsContext is a plugin for reporting Hadoop Metrics through
   * syslog protocol.  Usage:
   * 
   * Copy hadoop-metrics.properties file from CHUKWA_HOME/conf to HADOOP_HOME/conf.
   * Copy chukwa-hadoop-*-client.jar and json.jar to HADOOP_HOME/lib
   * 
   */
  import org.apache.hadoop.metrics.ContextFactory;
  import org.apache.hadoop.metrics.MetricsException;
  import org.apache.hadoop.metrics.spi.AbstractMetricsContext;
  import org.apache.hadoop.metrics.spi.OutputRecord;
  import org.apache.log4j.Logger;
  import org.apache.log4j.PatternLayout;
  import org.json.simple.JSONObject;
  import java.util.TreeMap;
  import java.util.Map;
  import java.util.Collection;
  import java.io.IOException;
  import org.apache.hadoop.chukwa.util.ExceptionUtil;
  
  public class Log4JMetricsContext extends AbstractMetricsContext {
    Logger log = Logger.getLogger(Log4JMetricsContext.class);
    Logger out = null; 
    static final Object lock = new Object();
  
    /* Configuration attribute names */
    protected static final String PERIOD_PROPERTY = "period";
    protected static final String HOST_PROPERTY = "host";
    protected static final String PORT_PROPERTY = "port";  
  
    protected int period = 0;
    protected String host = "localhost";
    protected int port = 9095;
    
    /** Creates a new instance of MetricsContext */
    public Log4JMetricsContext() {
    }
  
    public void init(String contextName, ContextFactory factory) {
      super.init(contextName, factory);
     
      String periodStr = getAttribute(PERIOD_PROPERTY);
      if (periodStr != null) {
        int period = 0;
        try {
          period = Integer.parseInt(periodStr);
        } catch (NumberFormatException nfe) {
          log.debug(ExceptionUtil.getStackTrace(nfe));
        }
        if (period <= 0) {
          throw new MetricsException("Invalid period: " + periodStr);
        }
        setPeriod(period);
        this.period = period;
        log.info("Log4JMetricsContext." + contextName + ".period=" + period);
      }
      String host = getAttribute(HOST_PROPERTY);
      if (host != null) {
        this.host = host;
      }
      String port = getAttribute(PORT_PROPERTY);
      if (port != null) {
        this.port = Integer.parseInt(port);
      }
    }
  
    @Override
    protected void emitRecord(String contextName, String recordName,
        OutputRecord outRec) throws IOException {
      synchronized (lock) {
        if (out == null) {
          PatternLayout layout = new PatternLayout("%d{ISO8601} %p %c: %m%n");
            
          org.apache.log4j.net.SocketAppender appender = new org.apache.log4j.net.SocketAppender(host, port);
            
          appender.setName("chukwa.metrics." + contextName);
          appender.setLayout(layout);
            
          Logger logger = Logger.getLogger("chukwa.metrics." + contextName);
          logger.setAdditivity(false);
          logger.addAppender(appender);
          appender.activateOptions();
          out = logger;
        }
        JSONObject json = new JSONObject();
        try {
          json.put("contextName", contextName);
          json.put("recordName", recordName);
          json.put("timestamp", System.currentTimeMillis());
          json.put("period", period);
          for (String tagName : outRec.getTagNames()) {
            json.put(tagName, outRec.getTag(tagName));
          }
          for (String metricName : outRec.getMetricNames()) {
            json.put(metricName, outRec.getMetric(metricName));
          }
        } catch (Exception e) {
          log.warn("exception in Log4jMetricsContext:" , e);
        }
        out.info(json.toString());
      }
    }
  
    @Override
    public synchronized Map<String, Collection<OutputRecord>> getAllRecords() {
      Map<String, Collection<OutputRecord>> out = new TreeMap<String, Collection<OutputRecord>>();
  /*    for (String recordName : bufferedData.keySet()) {
        RecordMap recordMap = bufferedData.get(recordName);
        synchronized (recordMap) {
          List<OutputRecord> records = new ArrayList<OutputRecord>();
          Set<Entry<TagMap, MetricMap>> entrySet = recordMap.entrySet();
          for (Entry<TagMap, MetricMap> entry : entrySet) {
            OutputRecord outRec = new OutputRecord(entry.getKey(), entry.getValue());
            records.add(outRec);
          }
          out.put(recordName, records);
        }
      }*/
      return out;
    }
  }
  