lib/tasks/logs.rake in decidim-cdtb-0.2.1 vs lib/tasks/logs.rake in decidim-cdtb-0.3.0

- old
+ new

@@ -1,16 +1,118 @@ # frozen_string_literal: true namespace :cdtb do namespace :logs do - desc "Analize logs in Rails format. Counts the number of requests for each IP in the logs. Accepts a logfile param, it must be in log/." + desc "Analize logs in Rails format. Counts the number of requests for each IP in the logs. Accepts a log path param." task :num_rq_per_ip, [:logfile] do |_task, args| - logfile= args.logfile || "development.log" + file_path= args.logfile || "log/production.log" - file_path= "log/#{logfile}" first_cmd= "grep Started" piped_cmds= [%(grep " for "), "cut -d ' ' -f13", "sort", "uniq -c", "sort"].join(" | ") - puts "Running: `#{first_cmd} #{file_path} | #{piped_cmds}`" - puts `#{first_cmd} #{file_path} | #{piped_cmds}` + cmd= "#{first_cmd} #{file_path} | #{piped_cmds}" + + puts "Running: `#{cmd}`" + puts `#{cmd}` + end + + desc "Analize logs in Rails format. Counts the number of requests for each IP range in the logs. Accepts a log path param." + task :num_rq_per_ip_range, [:logfile] do |_task, args| + file_path= args.logfile || "log/production.log" + + first_cmd= "grep Started" + piped_cmds= [ + %(grep " for "), + # take the IP + "cut -d ' ' -f13", + # trim blank spaces + "awk '{$1=$1;print}'", + # range: only the first 2 blocks of the IP + "cut -d '.' -f1,2", + "sort", + "uniq -c", + "sort" + ].join(" | ") + cmd= "#{first_cmd} #{file_path} | #{piped_cmds}" + + puts "Running: `#{cmd}`" + puts `#{cmd}` + end + + desc 'Returns the duration, the order in the logs, and the timestamp of each "Completed" trace.' + task :slow_rq, [:logfile] do |_task, args| + # Based on the follwoing example execution: + # grep -e "Completed 200 OK in" log/development.log | ruby logparser.rb | sort + + file_path= args.logfile || "log/production.log" + + idx= 0 + File.open(file_path).each_line do |line| + idx += 1 + next unless line.include?("Completed 200 OK in") + + split= line.split("Completed 200 OK in") + second_part= split.last.strip + words= second_part.split + response_duration= words.first + puts "#{response_duration.rjust(7, "0")}, #{idx}, #{line[4, 22]}" + end + end + + desc "Most requested paths. Accepts a log path param, and an only_path to ignore the query part of the URL." + task :most_rq_paths, [:logfile, :only_path] do |_task, args| + file_path= args.logfile || "log/production.log" + + first_cmd= "grep Started" + piped_cmds= ["cut -d ' ' -f11"] + piped_cmds << "cut -d '?' -f 1" if args.only_path == "only_path" + piped_cmds+= ["sort", "uniq -c", "sort"] + cmd= "#{first_cmd} #{file_path} | #{piped_cmds.join(" | ")}" + + puts "Running: `#{cmd}`" + puts `#{cmd}` + end + + desc "Analizes output from num_rq_per_ip. Finds the country from each IP in the log file. Accepts a log path param." + task :geolocate_ips, [:logfile] do |_task, args| + file_path= args.logfile || "log/num_rq_per_ip.log" + + cmd= [ + # strip spaces + "awk '{$1=$1;print}' #{file_path}", + "cut -d ' ' -f2", + "sort" + ].join(" | ") + + cmd_out= `#{cmd}` + cmd_out.each_line do |ip| + ip= ip.strip + locations= Geocoder.search(ip) + location_rs= locations.first + country= parse_nominatim_result(location_rs) || parse_ipinfoio_result(location_rs) || "N/F" + puts "#{ip},#{country}" + end + end + + def parse_nominatim_result(result) + result&.dig("address", "country") + end + + def parse_ipinfoio_result(result) + result&.dig("country") + end + + desc "Lists from the output of geolocated_ips. Finds the country from each IP in the csv file. Accepts a file path param." + task :bannable_ips, [:path, :countries] do |_task, args| + file_path= args.path || "tmp/geolocated_ips.csv" + countries= args.countries || %w[FR GB IT PT] + + cmd= ["grep -v ES #{file_path}"] + countries.each do |country_iso| + cmd << "grep -v #{country_iso}" + end + cmd << "cut -d ',' -f1" + cmd << "sort" + + puts `#{cmd.join(" | ")}` end end end