# Time 2015-01-26 17:30:16 # Author lizanle # Description 日志帮助类 module SystemLogHelper class SystemLog class << self # Time 2015-01-26 17:29:17 # Author lizanle # Description 分页(支持多关键字查询) def logo_data(page, per, search, day) logs = find_all_logs day if logs.empty? #如果返回的是空數組,就說明日誌文件不存在 return logs end # 根据search参数来决定是否需要查询 keywords = search if keywords && !keywords.strip.blank? # 把keywords转化成正则表达式数组 keywords = keywords.strip.split(/\s+/).collect! { |w| Regexp.new(w, 'i') } # 一条记录应该匹配每个关键字 log =~ r 是对log记录进行判断是否符合r的正则表达式 logs = logs.find_all do |log| keywords.all? { |r| log =~ r && !(log =~ Regexp.new("SystemLogController#",'i')) } end #用Kaminari分页 logs = Kaminari.paginate_array(logs).page(page).per(per).collect! { |log| parse(log) } #将分页后的记录的搜索结果添加样式,样式中的\0是给给r占位置的。 logs.collect! do |log| keywords.each { |r| log.gsub!(r, '\0') } log end else logs = Kaminari.paginate_array(logs).page(page).per(per).collect! { |log| parse(log) } # 过滤掉日志中日志分析请求 logs.collect! do |log| log = "" if log =~ Regexp.new("SystemLogController",'i') log end end logs end # Time 2015-01-26 17:28:57 # Author lizanle # Description 清除日誌 def clear day if File::exists?(logfile_path day) File.open(logfile_path(day), 'w') do |f| f.print '' end else end end # Time 2015-01-26 17:28:49 # Author lizanle # Description 讀取日誌 private def find_all_logs day if File::exists?(logfile_path day) File.open(logfile_path day) do |f| #打开文件,并按照正则表达式切分,逆序,最新一个记录可以扔掉(因为最新的记录永远都是访问System_log) f.read.split("Processing").reverse[1..-1] end else [] end end # Time 2015-01-26 17:28:34 # Author lizanle # Description 日志文件的路径,一般在Rails.root/log下,根据环境配置 # 依次记录到product.log development.log test.log中 def logfile_path day #将日期处理成2015-01-01的形式 unless day.nil? dayArr = day.split('-') if dayArr[1].length == 1 dayArr[1] = "0" + dayArr[1] end if dayArr[2].length == 1 dayArr[2] = "0" + dayArr[2] end day = dayArr.join('-') end #如果不是當天,則需要加後綴 if !day.nil? && !day.strip.blank? && day != Time.now.strftime("%Y-%m-%d") File.join(Rails.root, "log", "#{Rails.env}.log.#{day.gsub('-', '')}") else File.join(Rails.root, "log", "#{Rails.env}.log") end end # Time 2015-01-26 17:28:22 # Author lizanle # Description 替換換行符 def parse(log) ERB::Util.html_escape(log.gsub(/\e\[[\d;m]+/, '')).gsub("\n", "
") end # Time 2015-01-26 17:28:07 # Author lizanle # Description 定义响应正则表达式 2015-01-20 11:31:13 INFO -- Completed 200 OK in 125ms (Views: 81.0ms | ActiveRecord: 2.0ms) def response_regex 'Completed \d+ \w+ in (\d+)ms \(Views: (\d+\.\d+)?ms \| ActiveRecord: (\d+\.\d+)?ms\)' end # Time 2015-01-26 17:27:51 # Author lizanle # Description 将一条记录中的地址主机等都分析出来 def get_status(paragraph) request_regex = 'Started GET \"(\/.*)\" for ([\d]+\.[\d]+\.[\d]+\.[\d]+) at [\d]*-([\d]*-[\d]* [\d]*:[\d]*:[\d]*)' controller_regex = 'Processing by ([\w]+#[\w]+)' page_time_regex = 'Views: \d+(\.\d+)?ms' activeRecord_time_regex = 'ActiveRecord: \d+(\.\d+)?ms' #解析请求中的正则,主机,时间 if paragraph.match(request_regex) != nil request_url = paragraph.match(request_regex)[1] #正则表达式中的括号能够截取成数组 request_host = paragraph.match(request_regex)[2] request_at = paragraph.match(request_regex)[3] end #解析控制器 if paragraph.match(controller_regex) != nil controller_name = paragraph.match(controller_regex)[1] end #解析响应时间以及计算百分比 if paragraph.match(response_regex) != nil #print(paragraph.match(response_regex)) total_time = paragraph.match(response_regex)[1] page_time = paragraph.match(response_regex)[2] activeRecord_time = paragraph.match(response_regex)[3] page_time_percent = page_time.to_f/(total_time.to_f) activeRecord_time_percent = activeRecord_time.to_f/(total_time.to_f) else end #将解析结果当做一条记录数组返回 request_status = [request_url, request_host, request_at, controller_name, total_time, page_time, page_time_percent, activeRecord_time, activeRecord_time_percent] request_status end # Time 2015-01-26 16:41:51 # Author lizanle # Description 分析日志 public def analysis day csv = Array.new #如果文件不存在,则直接返回空数组 if File::exists?(logfile_path day) File.open(logfile_path(day), "r:utf-8") do |file| paragraph = "" begin_flag = false # 对每一行进行判断 file.each do |line| # 以"Started GET "开头为一个paragraph #print(line.match('[\d]*-([\d]*-[\d]* [\d]*:[\d]*:[\d]*) INFO -- Started GET ') == nil) if (line.match('[\d]*-([\d]*-[\d]* [\d]*:[\d]*:[\d]*) \w+ -- Started GET ') != nil) if !begin_flag begin_flag = true paragraph.concat(line) else # 另一个paragraph的开头 if (paragraph.match(response_regex) != nil) csv << get_status(paragraph) end begin_flag = true paragraph = line end else if begin_flag paragraph.concat(line) else end end end end end csv end end end end