Updated

app/models / signature_logs.rb

D
171 lines of codes
28 methods
7.0 complexity/method
3 churn
195.26 complexity
74 duplications
require 'aws-sdk' require 'ipaddr' class SignatureLogs
  1. SignatureLogs has no descriptive comment
class Log
  1. SignatureLogs::Log has no descriptive comment
  2. SignatureLogs::Log has at least 16 methods
PATTERN = /(?<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:, (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))* - .{0}- \[(?<day>[\d]{2})\/(?<month>[\w]+)\/(?<year>[\d]{4})\:(?<hour>[\d]{2})\:(?<min>[\d]{2})\:(?<sec>[\d]{2}) [^$]+\] "(?<method>GET|POST|PUT|DELETE) (?<uri>[^\s]+?) HTTP\/1\.1" (?<response>[\d]+) [\d]+ "(?<referrer>[^\s]+?)" "(?<agent>[^\"]+?)"/ MONTHS = %w[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec] attr_reader :message, :data def initialize(message) @message = message @data = message.match(PATTERN) end def blank? data.nil?
  1. SignatureLogs::Log#blank? performs a nil-check
end def ip_address if present?
  1. SignatureLogs::Log tests 'present?' at least 7 times Locations: 0 1 2 3 4 5 6
@ip_address ||= data && ::IPAddr.new(data["ip"]) end end def timestamp if present?
  1. SignatureLogs::Log tests 'present?' at least 7 times Locations: 0 1 2 3 4 5 6
@timestamp ||= data && ::Time.utc(year, month, day, hour, min, sec).in_time_zone end end def method data["method"] if present?
  1. SignatureLogs::Log tests 'present?' at least 7 times Locations: 0 1 2 3 4 5 6
end def uri data["uri"] if present?
  1. SignatureLogs::Log tests 'present?' at least 7 times Locations: 0 1 2 3 4 5 6
end def response data["response"] if present?
  1. SignatureLogs::Log tests 'present?' at least 7 times Locations: 0 1 2 3 4 5 6
end def referrer data["referrer"] if present?
  1. SignatureLogs::Log tests 'present?' at least 7 times Locations: 0 1 2 3 4 5 6
end def agent data["agent"] if present?
  1. SignatureLogs::Log tests 'present?' at least 7 times Locations: 0 1 2 3 4 5 6
end def ==(other) return false unless other.is_a?(self.class) message == other.message end private def year; data["year"].to_i; end def month; MONTHS.index(data["month"]) + 1; end def day; data["day"].to_i; end def hour; data["hour"].to_i; end def min; data["min"].to_i; end def sec; data["sec"].to_i; end end include Enumerable attr_reader :signature delegate :created_at, to: :signature delegate :ip_address, to: :signature delegate :validated_at, to: :signature delegate :validated_ip, to: :signature delegate :size, :empty?, to: :logs class << self def find(id) new(id) end end def initialize(id) @signature = Signature.find(id) end def each(&block) logs.each { |log| yield log } end private def client @client ||= Aws::CloudWatchLogs::Client.new end def log_group_name
  1. SignatureLogs#log_group_name doesn't depend on instance state (maybe move it to another class?)
ENV.fetch("NGINX_LOG_GROUP_NAME", "nginx-access-logs") end def ms(time)
  1. SignatureLogs#ms doesn't depend on instance state (maybe move it to another class?)
(time.to_f * 1000).to_i end def logs @logs ||= fetch_events.map { |e| Log.new(e.message) }.reject(&:blank?).sort_by(&:timestamp)
  1. SignatureLogs#logs has the variable name 'e'
end def fetch_events if overlapping? fetch_combined_events else fetch_create_events + fetch_validate_events end end def overlapping? return false unless validated_at return false unless validated_ip return false unless ip_address == validated_ip (created_at + 5.minutes) >= (validated_at - 5.minutes)
  1. SignatureLogs#overlapping? calls '5.minutes' 2 times
end def fetch_create_events
  1. Similar code found in 2 nodes Locations: 0 1
request = { log_group_name: log_group_name, start_time: ms(created_at - 5.minutes),
  1. SignatureLogs#fetch_create_events calls '5.minutes' 2 times Locations: 0 1
end_time: ms(created_at + 5.minutes),
  1. SignatureLogs#fetch_create_events calls '5.minutes' 2 times Locations: 0 1
filter_pattern: ip_address, interleaved: true } client.filter_log_events(request).events rescue Aws::CloudWatchLogs::Errors::ServiceError => e
  1. SignatureLogs#fetch_create_events has the variable name 'e'
[] end def fetch_validate_events
  1. SignatureLogs#fetch_validate_events has approx 6 statements
return [] unless validated_at return [] unless validated_ip request = { log_group_name: log_group_name, start_time: ms(validated_at - 5.minutes),
  1. SignatureLogs#fetch_validate_events calls '5.minutes' 2 times Locations: 0 1
end_time: ms(validated_at + 5.minutes),
  1. SignatureLogs#fetch_validate_events calls '5.minutes' 2 times Locations: 0 1
filter_pattern: validated_ip, interleaved: true } client.filter_log_events(request).events rescue Aws::CloudWatchLogs::Errors::ServiceError => e
  1. SignatureLogs#fetch_validate_events has the variable name 'e'
[] end def fetch_combined_events
  1. Similar code found in 2 nodes Locations: 0 1
request = { log_group_name: log_group_name, start_time: ms(created_at - 5.minutes),
  1. SignatureLogs#fetch_combined_events calls '5.minutes' 2 times Locations: 0 1
end_time: ms(validated_at + 5.minutes),
  1. SignatureLogs#fetch_combined_events calls '5.minutes' 2 times Locations: 0 1
filter_pattern: ip_address, interleaved: true } client.filter_log_events(request).events rescue Aws::CloudWatchLogs::Errors::ServiceError => e
  1. SignatureLogs#fetch_combined_events has the variable name 'e'
[] end end