目的

实时监听多个目录下的日志文件,如有新文件切换到新文件,并同步写入kafka,同时记录日志文件的行位置,以应对进程异常退出,能从上次的文件位置开始读取(考虑到效率,这里是每100条记一次,可调整)

源码

  1. import java.io.BufferedReader;
  2. import java.io.BufferedWriter;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileNotFoundException;
  6. import java.io.FileReader;
  7. import java.io.FileWriter;
  8. import java.io.IOException;
  9. import java.io.LineNumberReader;
  10. import java.util.ArrayList;
  11. import java.util.Collection;
  12. import java.util.HashMap;
  13. import java.util.List;
  14. import java.util.Properties;
  15. import java.util.Random;
  16. import kafka.javaapi.producer.Producer;
  17. import kafka.producer.KeyedMessage;
  18. import kafka.producer.ProducerConfig;
  19. ;
  20. public class XTail_Line {
  21. public static class TailFileThread extends Thread
  22. {
  23. File file;
  24. LineNumberReader randomFile=null;
  25. String newfile=null;
  26. String thisfile=null;
  27. String prefile=null;
  28. private long lastTimeFileSize = 0;
  29. private String drname=null;
  30. int ln=0;
  31. int beginln=0;
  32. private Producer<String,String> inner;
  33. java.util.Random ran = new Random();
  34. String topicname=null;
  35. public TailFileThread(String path,String drname,String topicname) throws FileNotFoundException, IOException
  36. {
  37. file=new File(path);
  38. this.drname=drname;
  39. this.topicname=topicname;
  40. Properties properties = new Properties();
  41. //   properties.load(ClassLoader.getSystemResourceAsStream("producer.properties"));
  42. properties.load(new FileInputStream("producer.properties"));
  43. ProducerConfig config = new ProducerConfig(properties);
  44. inner = new Producer<String, String>(config);
  45. }
  46. public void send(String topicName,String message) {
  47. if(topicName == null || message == null){
  48. return;
  49. }
  50. //   KeyedMessage<String, String> km = new KeyedMessage<String, String>(topicName,message);
  51. //随机作为key,hash分散到各个分区
  52. KeyedMessage<String, String> km = new KeyedMessage<String, String>(topicName,String.valueOf(ran.nextInt(9)),message);
  53. //   KeyedMessage<String, String> km = new KeyedMessage<String, String>(topicName,message,message);
  54. inner.send(km);
  55. }
  56. public void send(String topicName,Collection<String> messages) {
  57. if(topicName == null || messages == null){
  58. return;
  59. }
  60. if(messages.isEmpty()){
  61. return;
  62. }
  63. List<KeyedMessage<String, String>> kms = new ArrayList<KeyedMessage<String, String>>();
  64. for(String entry : messages){
  65. KeyedMessage<String, String> km = new KeyedMessage<String, String>(topicName,entry);
  66. kms.add(km);
  67. }
  68. inner.send(kms);
  69. }
  70. public void close(){
  71. inner.close();
  72. }
  73. public String getNewFile(File file)
  74. {
  75. File[] fs=file.listFiles();
  76. long maxtime=0;
  77. String newfilename="";
  78. for (int i=0;i<fs.length;i++)
  79. {
  80. if (fs[i].isFile()&&fs[i].lastModified()>maxtime)
  81. {
  82. maxtime=fs[i].lastModified();
  83. newfilename=fs[i].getAbsolutePath();
  84. }
  85. }
  86. return newfilename;
  87. }
  88. //写入文件名及行号
  89. public void writePosition(String path,int rn)
  90. {
  91. try {
  92. BufferedWriter out = new BufferedWriter(new FileWriter(drname+".position"));
  93. out.write(path+","+rn);
  94. out.close();
  95. } catch (IOException e) {
  96. }
  97. }
  98. public void run()
  99. {
  100. thisfile=getNewFile(file);
  101. prefile=thisfile;
  102. //访问position文件,如果记录了文件路径,及行号,则定位,否则使用最新的文件
  103. try {
  104. BufferedReader br=new BufferedReader(new FileReader(drname+".position"));
  105. String line=br.readLine();
  106. if (line!=null &&line.contains(","))
  107. {
  108. thisfile=line.split(",")[0];
  109. prefile=thisfile;
  110. beginln=Integer.parseInt(line.split(",")[1]);
  111. }
  112. } catch (FileNotFoundException e2) {
  113. // TODO Auto-generated catch block
  114. e2.printStackTrace();
  115. }
  116. catch (IOException e2) {
  117. // TODO Auto-generated catch block
  118. e2.printStackTrace();
  119. }
  120. //指定文件可读可写
  121. try {
  122. randomFile = new LineNumberReader(new FileReader(thisfile));
  123. } catch (FileNotFoundException e) {
  124. // TODO Auto-generated catch block
  125. e.printStackTrace();
  126. }
  127. while (true)
  128. {
  129. try {
  130. Thread.sleep(100);
  131. //调用interrupt方法后
  132. if(isInterrupted())
  133. {
  134. System.out.println("Interrupted...");
  135. break;
  136. }
  137. } catch (InterruptedException e1) {
  138. // TODO Auto-generated catch block
  139. e1.printStackTrace();
  140. }
  141. try {
  142. //获得变化部分的
  143. //  randomFile.seek(lastTimeFileSize);
  144. String tmp = "";
  145. while( (tmp = randomFile.readLine())!= null) {
  146. int currln=randomFile.getLineNumber();
  147. //beginln默认为0
  148. if (currln>beginln)
  149. send(topicname,new String(tmp.getBytes("utf8")));
  150. ln++;
  151. //每发生一条写一次影响效率
  152. if (ln>100)
  153. {
  154. writePosition(thisfile,currln);
  155. ln=0;
  156. }
  157. }
  158. thisfile=getNewFile(file);
  159. if(!thisfile.equals(prefile))
  160. {
  161. randomFile.close();
  162. randomFile = new LineNumberReader(new FileReader(thisfile));
  163. prefile=thisfile;
  164. beginln=0;
  165. }
  166. } catch (IOException e) {
  167. throw new RuntimeException(e);
  168. }
  169. }
  170. }
  171. }
  172. public static void main(String[] args) throws Exception {
  173. /*
  174. LogView view = new LogView();
  175. final File tmpLogFile = new File("D:\\test.txt");
  176. view.realtimeShowLog(tmpLogFile);
  177. */
  178. if (args.length!=2)
  179. {
  180. System.out.println("usage:topicname pathname");
  181. System.exit(1);
  182. }
  183. String topicname=args[0];
  184. String pathname=args[1];
  185. HashMap<String,TailFileThread> hm=new HashMap<String,TailFileThread>();
  186. File tmpLogFile = new File(pathname);
  187. File[] fs=tmpLogFile.listFiles();
  188. while (true)
  189. {
  190. fs=tmpLogFile.listFiles();
  191. for (int i=0;i<fs.length;i++)
  192. {
  193. if(fs[i].isDirectory())
  194. {
  195. String path=fs[i].getAbsolutePath();
  196. //以drname作为position文件名
  197. String drname=fs[i].getName();
  198. //如果该目录对应的处理线程已经存在,判断是否存活
  199. if (drname.contains("xx") || drname.contains("yy") || drname.contains("zz") || drname.contains("aa")
  200. )
  201. {
  202. if (hm.containsKey(path))
  203. {
  204. if (!hm.get(path).isAlive())
  205. {
  206. hm.get(path).interrupt();
  207. TailFileThread tt=new TailFileThread(path,drname,topicname);
  208. tt.start();
  209. hm.put(path, tt);
  210. }
  211. }
  212. //如果不存在,新建
  213. else
  214. {
  215. TailFileThread tt=new TailFileThread(path,drname,topicname);
  216. tt.start();
  217. hm.put(path, tt);
  218. }
  219. }
  220. }           //System.out.println(fs[i].getAbsolutePath());
  221. }
  222. Thread.sleep(100);
  223. }
  224. }
  225. }

转:http://blog.csdn.net/u011750989/article/details/21957741

java实时监听日志写入kafka(多目录)的更多相关文章

  1. java实时监听日志写入kafka(转)

    原文链接:http://www.sjsjw.com/kf_cloud/article/020376ABA013802.asp 目的 实时监听某目录下的日志文件,如有新文件切换到新文件,并同步写入kaf ...

  2. java实时监听日志写入kafka

    目的 实时监听某目录下的日志文件,如有新文件切换到新文件,并同步写入kafka,同时记录日志文件的行位置,以应对进程异常退出,能从上次的文件位置开始读取(考虑到效率,这里是每100条记一次,可调整) ...

  3. 20180530利用Maxwell组件实时监听Mysql的binlog日志

    转自:https://blog.csdn.net/qq_30921461/article/details/78320750 http://kafka.apache.org/quickstart htt ...

  4. Java实现系统目录实时监听更新。

    SDK1.7新增的nio WatchService能完美解决这个问题.美中不足是如果部署在window系统下会出现莫名其妙的文件夹占用异常导致子目录监听失效,linux下则完美运行.这个问题着实让人头 ...

  5. js 实时监听input中值变化

    注意:用到了jquery需要引入jquery.min.js. 需求: 1.每个地方需要分别打分,总分为100; 2.第一个打分总分为40; 3.第二个打分总分为60. 注意:需要判断null.&quo ...

  6. ORACLE清理、截断监听日志文件(listener.log)

    在ORACLE数据库中,如果不对监听日志文件(listener.log)进行截断,那么监听日志文件(listener.log)会变得越来越大,想必不少人听说过关于"LISTENER.LOG日 ...

  7. Java线程监听,意外退出线程后自动重启

    Java线程监听,意外退出线程后自动重启 某日,天朗气清,回公司,未到9点,刷微博,顿觉问题泛滥,惊恐万分! 前一天写了一个微博爬行程序,主要工作原理就是每隔2分钟爬行一次微博,获取某N个关注朋友微博 ...

  8. Android实时监听网络状态

    Android实时监听网络状态(1)   其实手机在网络方面的的监听也比较重要,有时候我们必须实时监控这个程序的实时网络状态,android在网络断开与连接的时候都会发出广播,我们通过接收系统的广播就 ...

  9. Oracle数据库运维:要对监听日志文件(listener.log)进行定期清理,如果不定期清理,会遇到下面一些麻烦

    原文链接: http://www.lookdaima.com/WebForms/WebPages/Blanks/Pm/Docs/DocItemDetail.aspx?EmPreviewTypeV=2& ...

随机推荐

  1. svg保存为图片下载到本地

    今天给大家说一个将svg下载到本地图片的方法,这里我不得不吐槽一下,为啥博客园不可以直接上传本地文件给大家用来直接下载分享呢,好,吐槽到此为止! 这里需要用到一个js文件,名字自己起,内容如下: (f ...

  2. LINQ&EF任我行(二)--LinQ to Object

    (原创:灰灰虫的家http://hi.baidu.com/grayworm)LinQ to Objects是LinQ家庭的核心,其它的LinQ也使用了与LinQ to Objects相同的查询句法.最 ...

  3. Python开发环境Wing IDE使用教程之matplotlib 2D绘图库代码调试技巧

    Wing IDE是一个集成开发环境,可用于加快matplotlib2D图形库的Python代码的编写和调试进程.Wing IDE提供自动完成.调用提示.调试器,以及许多其他功能,可帮助用户编写.浏览和 ...

  4. 利用jQuery做登录界面的验证码

    主要是为了有效防止机器恶意注册,对某一个特定已注册用户用特定程序暴力破解方式进行不断的登陆尝试.验证码是现在很多网站注册/登录时必填的, 虽然对用户可能有点麻烦,但是对网站/社区来说这个功能还是很有必 ...

  5. leetcode:查找

    1.  word ladder 题目: Given two words (start and end), and a dictionary, find the length of shortest t ...

  6. 特殊矩阵的压缩存储(转自chunlanse2014)

    对称矩阵 对于一个矩阵结构显然用一个二维数组来表示是非常恰当的,但在有些情况下,比如常见的一些特殊矩阵,如三角矩阵.对称矩阵.带状矩阵.稀疏矩阵等,从节约存储空间的角度考虑,这种存储是不太合适的.下面 ...

  7. C++学习之继承中的成员访问控制

    由基类到派生类的过程中,在派生类里如何访问基类成员,以及派生类对象如何访问基类成员,是根据派生类在从基类派生时是以什么方式进行的派生:public.protect或者private.下面说一下在这三种 ...

  8. 在IDEA中创建Maven项目和添加tomcat

    IDEA中创建是一种创建maven项目的办法,但不推荐,因为没有使用统一的骨架,可以一开始就选择创建maven项目,步骤如下: 第一步 第二步:设置项目 第三步:进行配置好maven,加上 arche ...

  9. C#中索引器的实现过程,是否只能根据数字进行索引?

    描述一下C#中索引器的实现过程,是否只能根据数字进行索引? 答:索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,  使程序看起来更为直观,更容易编写,可以用任意类型.

  10. Kettle报表自动化

    来自我们牛逼哄哄的东哥的笔记 1.   2. 3. 选择数据库链接 贴报表SQL 4. 文件名:选择路径,excel文件由kettle自动创建,自己只需输入创建文件的名称. 拓展名:后缀写上 5. 此 ...