1.四个需求

  需求一:求contentsize的平均值、最小值、最大值

  需求二:请各个不同返回值的出现的数据 ===> wordCount程序

  需求三:获取访问次数超过N次的IP地址

  需求四:获取访问次数最多的前K个endpoint的值 ==> TopN

2.主程序LogAnalyzer.scala

  1. package com.ibeifeng.bigdata.spark.core.log
  2.  
  3. import org.apache.spark.rdd.RDD
  4. import org.apache.spark.{SparkConf, SparkContext}
  5.  
  6. /**
  7. * Apache日志分析
  8. * Created by ibf on 01/15.
  9. */
  10. object LogAnalyzer {
  11. def main(args: Array[String]): Unit = {
  12. val conf = new SparkConf()
  13. .setAppName("log-analyzer")
  14. .setMaster("local[*]")
  15. .set("spark.eventLog.enabled", "true")
  16. .set("spark.eventLog.dir", "hdfs://hadoop-senior01:8020/spark-history")
  17. val sc = SparkContext.getOrCreate(conf)
  18.  
  19. // ================日志分析具体代码==================
  20. // HDFS上日志存储路径
  21. val path = "/beifeng/spark/access/access.log"
  22.  
  23. // 创建rdd
  24. val rdd = sc.textFile(path)
  25.  
  26. // rdd转换,返回进行后续操作
  27. val apacheAccessLog: RDD[ApacheAccessLog] = rdd
  28. // 过滤数据
  29. .filter(line => ApacheAccessLog.isValidateLogLine(line))
  30. .map(line => {
  31. // 对line数据进行转换操作
  32. ApacheAccessLog.parseLogLine(line)
  33. })
  34.  
  35. // 对多次时候用的rdd进行cache
  36. apacheAccessLog.cache()
  37.  
  38. // 需求一:求contentsize的平均值、最小值、最大值
  39. /*
  40. * The average, min, and max content size of responses returned from the server.
  41. * */
  42. val contentSizeRDD: RDD[Long] = apacheAccessLog
  43. // 提取计算需要的字段数据
  44. .map(log => (log.contentSize))
  45.  
  46. // 对重复使用的RDD进行cache
  47. contentSizeRDD.cache()
  48.  
  49. // 开始计算平均值、最小值、最大值
  50. val totalContentSize = contentSizeRDD.sum()
  51. val totalCount = contentSizeRDD.count()
  52. val avgSize = 1.0 * totalContentSize / totalCount
  53. val minSize = contentSizeRDD.min()
  54. val maxSize = contentSizeRDD.max()
  55.  
  56. // 当RDD不使用的时候,进行unpersist
  57. contentSizeRDD.unpersist()
  58.  
  59. // 结果输出
  60. println(s"ContentSize Avg:${avgSize}, Min: ${minSize}, Max: ${maxSize}")
  61.  
  62. // 需求二:请各个不同返回值的出现的数据 ===> wordCount程序
  63. /*
  64. * A count of response code's returned.
  65. * */
  66. val responseCodeResultRDD = apacheAccessLog
  67. // 提取需要的字段数据, 转换为key/value键值对,方便进行reduceByKey操作
  68. // 当连续出现map或者flatMap的时候,将多个map/flatMap进行合并
  69. .map(log => (log.responseCode, 1))
  70. // 使用reduceByKey函数,按照key进行分组后,计算每个key出现的次数
  71. .reduceByKey(_ + _)
  72.  
  73. // 结果输出
  74. println(s"""ResponseCode :${responseCodeResultRDD.collect().mkString(",")}""")
  75.  
  76. // 需求三:获取访问次数超过N次的IP地址
  77. // 需求三额外:对IP地址进行限制,部分黑名单IP地址不统计
  78. /*
  79. * All IPAddresses that have accessed this server more than N times.
  80. * 1. 计算IP地址出现的次数 ===> WordCount程序
  81. * 2. 数据过滤
  82. * */
  83. val blackIP = Array("200-55-104-193.dsl.prima.net.ar", "10.0.0.153", "208-38-57-205.ip.cal.radiant.net")
  84. // 由于集合比较大,将集合的内容广播出去
  85. val broadCastIP = sc.broadcast(blackIP)
  86. val N = 10
  87. val ipAddressRDD = apacheAccessLog
  88. // 过滤IP地址在黑名单中的数据
  89. .filter(log => !broadCastIP.value.contains(log.ipAddress))
  90. // 获取计算需要的IP地址数据,并将返回值转换为Key/Value键值对类型
  91. .map(log => (log.ipAddress, 1L))
  92. // 使用reduceByKey函数进行聚合操作
  93. .reduceByKey(_ + _)
  94. // 过滤数据,要求IP地址必须出现N次以上
  95. .filter(tuple => tuple._2 > N)
  96. // 获取满足条件IP地址, 为了展示方便,将下面这行代码注释
  97. // .map(tuple => tuple._1)
  98.  
  99. // 结果输出
  100. println(s"""IP Address :${ipAddressRDD.collect().mkString(",")}""")
  101.  
  102. // 需求四:获取访问次数最多的前K个endpoint的值 ==> TopN
  103. /*
  104. * The top endpoints requested by count.
  105. * 1. 先计算出每个endpoint的出现次数
  106. * 2. 再进行topK的一个获取操作,获取出现次数最多的前K个值
  107. * */
  108. val K = 10
  109. val topKValues = apacheAccessLog
  110. // 获取计算需要的字段信息,并返回key/value键值对
  111. .map(log => (log.endpoint, 1))
  112. // 获取每个endpoint对应的出现次数
  113. .reduceByKey(_ + _)
  114. // 获取前10个元素, 而且使用我们自定义的排序类
  115. .top(K)(LogSortingUtil.TupleOrdering)
  116. // 如果只需要endpoint的值,不需要出现的次数,那么可以通过map函数进行转换
  117. // .map(_._1)
  118.  
  119. // 结果输出
  120. println(s"""TopK values:${topKValues.mkString(",")}""")
  121.  
  122. // 对不在使用的rdd,去除cache
  123. apacheAccessLog.unpersist()
  124.  
  125. // ================日志分析具体代码==================
  126.  
  127. sc.stop()
  128. }
  129. }

3.需要的辅助类一(返回匹配的日志)

  1. package com.ibeifeng.bigdata.spark.core.log
  2.  
  3. import scala.util.matching.Regex
  4.  
  5. /**
  6. * 64.242.88.10 - - [07/Mar/2004:16:05:49 -0800] "GET /twiki/bin/edit/Main/Double_bounce_sender?topicparent=Main.ConfigurationVariables HTTP/1.1" 401 12846
  7. * Created by ibf on 01/15.
  8. */
  9. case class ApacheAccessLog(
  10. ipAddress: String, // IP地址
  11. clientId: String, // 客户端唯一标识符
  12. userId: String, // 用户唯一标识符
  13. serverTime: String, // 服务器时间
  14. method: String, // 请求类型/方式
  15. endpoint: String, // 请求的资源
  16. protocol: String, // 请求的协议名称
  17. responseCode: Int, // 请求返回值:比如:200、401
  18. contentSize: Long // 返回的结果数据大小
  19. )
  20.  
  21. /**
  22. * 64.242.88.10 - - [07/Mar/2004:16:05:49 -0800] "GET /twiki/bin/edit/Main/Double_bounce_sender?topicparent=Main.ConfigurationVariables HTTP/1.1" 401 12846
  23. * on 01/15.
  24. * 提供一些操作Apache Log的工具类供SparkCore使用
  25. */
  26. object ApacheAccessLog {
  27. // Apache日志的正则
  28. val PARTTERN: Regex =
  29. """^(\S+) (\S+) (\S+) \[([\w:/]+\s[+\-]\d{4})\] "(\S+) (\S+) (\S+)" (\d{3}) (\d+)""".r
  30.  
  31. /**
  32. * 验证一下输入的数据是否符合给定的日志正则,如果符合返回true;否则返回false
  33. *
  34. * @param line
  35. * @return
  36. */
  37. def isValidateLogLine(line: String): Boolean = {
  38. val options = PARTTERN.findFirstMatchIn(line)
  39.  
  40. if (options.isEmpty) {
  41. false
  42. } else {
  43. true
  44. }
  45. }
  46.  
  47. /**
  48. * 解析输入的日志数据
  49. *
  50. * @param line
  51. * @return
  52. */
  53. def parseLogLine(line: String): ApacheAccessLog = {
  54. if (!isValidateLogLine(line)) {
  55. throw new IllegalArgumentException("参数格式异常")
  56. }
  57.  
  58. // 从line中获取匹配的数据
  59. val options = PARTTERN.findFirstMatchIn(line)
  60.  
  61. // 获取matcher
  62. val matcher = options.get
  63.  
  64. // 构建返回值
  65. ApacheAccessLog(
  66. matcher.group(1), // 获取匹配字符串中第一个小括号中的值
  67. matcher.group(2),
  68. matcher.group(3),
  69. matcher.group(4),
  70. matcher.group(5),
  71. matcher.group(6),
  72. matcher.group(7),
  73. matcher.group(8).toInt,
  74. matcher.group(9).toLong
  75. )
  76. }
  77. }

4.需要的辅助类二(自定义的一个二元组的比较器,方便进行TopN)

  1. package com.ibeifeng.bigdata.spark.core.log
  2.  
  3. /**
  4. * Created by ibf on 01/15.
  5. */
  6. object LogSortingUtil {
  7.  
  8. /**
  9. * 自定义的一个二元组的比较器
  10. */
  11. object TupleOrdering extends scala.math.Ordering[(String, Int)] {
  12. override def compare(x: (String, Int), y: (String, Int)): Int = {
  13. // 按照出现的次数进行比较,也就是按照二元组的第二个元素进行比较
  14. x._2.compare(y._2)
  15. }
  16. }
  17.  
  18. }

024 关于spark中日志分析案例的更多相关文章

  1. 日志分析_使用shell完整日志分析案例

    一.需求分析 1. 日志文件每天生成一份(需要将日志文件定时上传至hdfs) 2. 分析日志文件中包含的字段:访问IP,访问时间,访问URL,访问状态,访问流量 3. 现在有"昨日" ...

  2. Spark离线日志分析,连接Spark出现报错

    首先,我的代码是这样的 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} object ...

  3. 大数据学习day20-----spark03-----RDD编程实战案例(1 计算订单分类成交金额,2 将订单信息关联分类信息,并将这些数据存入Hbase中,3 使用Spark读取日志文件,根据Ip地址,查询地址对应的位置信息

    1 RDD编程实战案例一 数据样例 字段说明: 其中cid中1代表手机,2代表家具,3代表服装 1.1 计算订单分类成交金额 需求:在给定的订单数据,根据订单的分类ID进行聚合,然后管理订单分类名称, ...

  4. spark SQL学习(综合案例-日志分析)

    日志分析 scala> import org.apache.spark.sql.types._ scala> import org.apache.spark.sql.Row scala&g ...

  5. Spark SQL慕课网日志分析(1)--系列软件(单机)安装配置使用

    来源: 慕课网 Spark SQL慕课网日志分析_大数据实战 目标: spark系列软件的伪分布式的安装.配置.编译 spark的使用 系统: mac 10.13.3 /ubuntu 16.06,两个 ...

  6. Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍

    网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edisonchou/p/4458219.html 网站日志分析项目案例 ...

  7. Hadoop学习笔记—20.网站日志分析项目案例(二)数据清洗

    网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:当前页面 网站日志分析项目案例 ...

  8. Hadoop学习笔记—20.网站日志分析项目案例(三)统计分析

    网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:http://www.cnbl ...

  9. 通过grep来进行日志分析,grep -C和配合awk实际对catalina.out使用案例

    本文介绍通过grep来进行日志分析,主要介绍grep -C和配合awk实际对catalina.out使用案例 grep可以对日志文件进行筛选,统计,查询,快速定位bug. 首先,你的日志需要比较规范, ...

随机推荐

  1. 01-go语言开始-HelloWorld

    以输出HelloWorld为目标 Go的发展史 Go语言诞生(2007年的谷歌)的背景是由于软件开发的新挑战: 多核硬件架构 超大规模分布式计算集群 Web模式导致的前所未有的开发规模和更新速度 Go ...

  2. 前端学习 -- Css -- overflow

    子元素默认是存在于父元素的内容区中,理论上讲子元素的最大可以等于父元素内容区大小.如果子元素的大小超过了父元素的内容区,则超过的大小会在父元素以外的位置显示,超出父元素的内容,我们称为溢出的内容.父元 ...

  3. linux basic ------ shell

    一般习惯把 shell 脚本语言和 shell 解释器统称为 shell,用 shell 脚本语言编写的程序简称脚本. shell 解释器 是用 c 语言写一个应用程序,它是用户使用 Unix / L ...

  4. linux开启swap(磁盘缓存)操作

    转载 2014年04月26日 14:41:15 4470 由于工作需要,要帮助同事查看linux服务器的缓存开启情况,经过查找资料,可确定通过以下方法确定Linux磁盘缓存是否已开启. 1.命令行下执 ...

  5. java基础基础总结----- 随机数(产生四个随机数)

    前言:在开发的时候经常会遇见,一些验证码登录,其实这些东西,很简单.我曾经开发过一个验证码登录的页面,那时用的插件.但是作为一个合格的开发者,要了解其内部的核心知识,有些东西,可以不深入了解,但是要做 ...

  6. sssss

    关于征集参加第五届世界互联网大会“世界互联网领先科技成果发布活动”相关成果的通知 2018年07月24日 08:55:00来源: 中国网信网     [打印] [纠错]     各有关单位/个人: 第 ...

  7. ActiveMQ基础教程JMS概述

    什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息 ...

  8. CSS规范 - 典型错误--(来自网易)

    不符合NEC规范的选择器用法 .class{} 不要以一个没有类别的样式作为主选择器,这样的选择器只能作为后代选择器使用,比如.m-xxx .class{}.        .m-xxx div{} ...

  9. the error about “no such file or directory”

    CHENYILONG Blog the error about "no such file or directory" when you get the question like ...

  10. PHP-Redis操作

    /*1.Connection*/ $redis = new Redis(); $redis->connect('127.0.0.1',6379,1);//短链接,本地host,端口为6379,超 ...