spark streaming 通过log4j 统一输出日志到kafka

10 篇文章 0 订阅
1.log4j 自定义输出到kafka appender
public class KafkaLog4jAppender2 extends AppenderSkeleton {


private Producer<String, String> producer = null;
private String topic = null;
private String brokerList = null;
private int batchSize = 0;


public void setTopic(String topic) {
this.topic = topic;
}


public void setBrokerList(String brokerList) {
this.brokerList = brokerList;
}


@Override
public void close() {
if (!this.closed) {
this.closed = true;
this.producer.close();
}
}


@Override
public boolean requiresLayout() {
return true;
}


// do with
// log4j.logger.org.apache.kafka=OFF ,or will endless loop
private Producer<String, String> getProducer() {
if (producer == null) {
Properties props = new Properties();
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("bootstrap.servers", brokerList);
props.put("batch.size", batchSize == 0 ? 1000 : batchSize);
producer = new KafkaProducer<String, String>(props);
}
return producer;
}


@Override
protected void append(LoggingEvent event) {
String message = subAppend(event);
System.out.println(message);
getProducer().send(new ProducerRecord<String, String>(this.topic, message));
}


private String subAppend(LoggingEvent event) {
return this.layout == null ? event.getRenderedMessage() : this.layout.format(event);
}
}




public class SparkKafkaPatternLayout extends PatternLayout {
public void setConversionPattern(String conversionPattern) {
String nodeInfo = System.getenv("NM_HOST") + "-" + System.getenv("JVM_PID");
String pattern = conversionPattern.replace("%nodeInfo", nodeInfo);
super.setConversionPattern(pattern);
}
}


log4j 配置文件:
log4j.rootLogger=info,kafka,R


log4j.appender.R=org.apache.log4j.RollingFileAppender 
log4j.appender.R.File=/tmp/test_ccd.log
log4j.appender.R.MaxFileSize=10MB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout 
log4j.appender.R.layout.ConversionPattern=appName_Ccd%d{yyyy-MM-dd HH:mm:ss}%p%c{2}:%L%m%n


log4j.appender.kafka=org.apache.kafka.log4jappender.KafkaLog4jAppender2
log4j.appender.kafka.topic=ccb
log4j.appender.kafka.brokerList=10.23.22.242:9092
#log4j.appender.kafka.layout=org.apache.log4j.PatternLayout
log4j.appender.kafka.layout=org.apache.kafka.log4jappender.SparkKafkaPatternLayout
log4j.appender.kafka.layout.ConversionPattern=appName_Ccd%nodeInfo%d{yyyy-MM-dd HH:mm:ss}%p%c{2}:%L%m


log4j.logger.org.apache.kafka=OFF


hive数据分隔符可以在windows上输入了 然后上传到linux。


怎么设置nodeName。
System.getProperty("")。
通过env获取到一下参数。
NM_HOST=HOST1
JVM_PID=820
APPLICATION_WEB_PROXY_BASE=/proxy/application_1513838240093_0003
可以设置到设置到 System.setProperty("","") 但是log4j加载之后才设System.setProperty已经晚了。
提交任务的入口类是org.apache.spark.deploy.SparkSubmit,后期才到自己写的main,这期间log4j已经加载了。
从日志上看,日志初始化在自己应用程序main之前执行,即使也在main的static里。

2.打包log4j-kafka-appender-0.1.jar上传/opt/cloudera/parcels/CDH-5.7.1-1.cdh5.7.1.p0.11/lib/spark/lib
在/etc/spark/conf.cloudera.spark_on_yarn/classpath.txt添加/opt/cloudera/parcels/CDH-5.7.1-1.cdh5.7.1.p0.11/lib/spark/lib/log4j-kafka-appender-0.1.jar
在每台NodeManager上操作,多台机器可以使用ssh,scp脚本实现。
尝试过把jar放在各个地方都不行。
也可以将自定义类压缩到spark-examples-1.6.0-cdh5.7.1-hadoop2.6.0-cdh5.7.1.jar,但是这样操作太麻烦。


怎么灵活依赖 log4j appender的自定义jar。  
https://www.cnblogs.com/xing901022/p/6426408.html
https://www.cnblogs.com/hujunfei/p/3624592.html
spark-class中的脚本
while IFS= read -d '' -r ARG; do
CMD+=("$ARG")
done < <("$RUNNER" -cp "$LAUNCH_CLASSPATH" org.apache.spark.launcher.Main "$@")
exec "${CMD[@]}"
("$RUNNER" -cp "$LAUNCH_CLASSPATH" org.apache.spark.launcher.Main "$@")  这句是执行Main方法输出将要执行的语句。
org.apache.spark.launcher.Main 这个类从源码看,除了JDK提供的类未应用其他Spark类(同包下类除外)。
真正执行submit的是exec "${CMD[@]}"
CMD+=("$ARG") 这句会 /usr/java/jdk1.7.0_67-cloudera/bin/java -cp xxx -XX:MaxPermSize=256m org.apache.spark.deploy.SparkSubmit #用户脚本中的参数
调用关系spark-submit -> spark-class -> load-spark-env.sh -> spark-env.sh
org.apache.spark.launcher.Main ->
在spark-env.sh里有读classpath相关类  export SPARK_DIST_CLASSPATH=$(paste -sd: "$SELF/classpath.txt") 
可以在java程序中用System.getenv("SPARK_DIST_CLASSPATH")获取到

所以最终只要将classpath.txt类中添加自定义类即可。


3.submit 脚本
location=`pwd`'/'
class=xxx
jars_path='libs'
jars_file='spark_jar_file.txt'
echo `ls -l $location$jars_path |awk 'NR>1 {print "'"$location"'""'"$jars_path"'""/"$9}'` > $jars_file
sed -i 's/[ ][ ]*/,/g' $jars_file
jars=`sed -n '1p' $location$jars_file`
jar=xxx.jar
app_name=xxx
files='config.properties,log4j-spark.properties'


/usr/bin/spark-submit  --class $class --master yarn-cluster  --jars $jars \
--files $location$files \
--name $app_name \
--conf spark.driver.extraJavaOptions=-Dlog4j.configuration=log4j-spark.properties \
--conf spark.executor.extraJavaOptions=-Dlog4j.configuration=log4j-spark.properties \
$location$jar & >> driver.log
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值