Class: SnitchReporting::SnitchOccurrence

Inherits:
ApplicationRecord
  • Object
show all
Defined in:
app/models/snitch_reporting/snitch_occurrence.rb

Overview

belongs_to :snitch_report string :http_method string :url text :user_agent text :backtrace text :context text :params text :headers

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#acting_userObject

Returns the value of attribute acting_user.



11
12
13
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 11

def acting_user
  @acting_user
end

#always_notifyObject

Returns the value of attribute always_notify.



11
12
13
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 11

def always_notify
  @always_notify
end

#should_notifyObject

Returns the value of attribute should_notify.



11
12
13
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 11

def should_notify
  @should_notify
end

Instance Method Details

#backtrace=(trace_lines) ⇒ Object

def self.staggered_occurrence_data

data = {}
occurrence_data_keys = all.map { |occurrence| occurrence.details.try(:keys) }.compact
longest_key_array = occurrence_data_keys.max_by(&:length) # Need the longest because `zip` removes any objects longer than the initial.
staggered_keys = longest_key_array&.zip(*occurrence_data_keys)&.flatten(1)&.compact&.uniq || []

data[:keys] = staggered_keys
data[:details] = all.map do |occurrence|
  detail_hash = {
    id: occurrence.id,
    details: []
  }
  occurrence_details = occurrence.details
  data[:keys].each_with_index do |detail_key, idx|
    occurrence_detail = occurrence_details[detail_key]
    detail_hash[:details][idx] =
      if occurrence_detail.is_a?(Array)
        occurrence_detail.join("\n")
      else
        occurrence_detail.to_s
      end
  end
  detail_hash
end

data

end

def from_data=(details_hash)

self.details = flatten_hash(details_hash)

end



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 55

def backtrace=(trace_lines)
  already_traced = []
  self.backtrace_data = trace_lines.map do |trace_line|
    next unless trace_line.include?("/app/") # && trace_line.exclude?("app/models/snitch_reporting")

    joined_path = file_lines_from_backtrace(trace_line)
    next if joined_path.include?(joined_path)
    already_traced << joined_path

    file_path, line_number = joined_path.split(":", 2)
    {
      file_path: remove_project_root(file_path),
      line_number: line_number,
      snippet: snippet_for_line(trace_line)
    }
  end.compact
  super(trace_lines.map { |trace_line| remove_project_root(trace_line) })
end

#file_lines_from_backtrace(backtrace_line) ⇒ Object



82
83
84
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 82

def file_lines_from_backtrace(backtrace_line)
  backtrace_line[/(\/?\w+\/?)+(\.\w+)+:?\d*/]
end

#filtered_backtraceObject



74
75
76
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 74

def filtered_backtrace
  backtrace_data&.map { |data| data&.dig(:file_path) }.compact
end

#notify?Boolean

def title

super.presence || "#{report.title} | Occurrence ##{id}"

end

def details

temp_details = super

temp_details.each do |detail_key, detail_val|
  next unless detail_val.to_s.first.in?(["[", "{"])

  begin
    temp_details[detail_key] = JSON.parse(detail_val)
  rescue JSON::ParserError
    nil
  end
end

temp_details

end

Returns:

  • (Boolean)


121
122
123
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 121

def notify?
  @should_notify ||= always_notify || report.resolved? || report.occurrence_count == 1
end

#remove_project_root(row) ⇒ Object



78
79
80
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 78

def remove_project_root(row)
  row.gsub(Rails.root.to_s, "[PROJECT_ROOT]")
end

#snippet_for_line(backtrace_line, line_count: 5) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/models/snitch_reporting/snitch_occurrence.rb', line 86

def snippet_for_line(backtrace_line, line_count: 5)
  file, num = backtrace_line.split(":")
  first_line_number = num.to_i
  offset_line_numbers = (line_count - 1) / 2
  line_numbers = (first_line_number - offset_line_numbers - 1)..(first_line_number + offset_line_numbers - 1)

  lines = File.open(file).read.split("\n").map.with_index { |line, idx| [line, idx + 1] }[line_numbers] rescue nil

  whitespace_count = lines.map { |line, _idx| line[/\s*/].length }.min

  lines.each_with_object({}) do |(line, idx), data|
    data[idx] = line[whitespace_count..-1]
  end
end