Module: RailsNexus::LoggedExceptionsHelper
- Includes:
- SourceCodeHelper
- Defined in:
- app/helpers/rails_nexus/logged_exceptions_helper.rb
Instance Method Summary collapse
-
#active_filter_pills ⇒ Object
Active filter pills for the filter bar.
- #exception_occurrence_count(exception) ⇒ Object
- #exception_searchable?(attribute) ⇒ Boolean
- #exception_status(exception) ⇒ Object
-
#exception_trend_data(days: 7) ⇒ Object
Simple sparkline data for stats.
- #filter_params_without(pill) ⇒ Object
- #filtered? ⇒ Boolean
-
#format_backtrace(backtrace, limit: nil) ⇒ Object
Format backtrace for display with optional collapse.
-
#git_blame_for_line(file_path, line_number, **_options) ⇒ Object
Get git blame for a file:line range.
- #listify(text) ⇒ Object
- #page_title(text) ⇒ Object
-
#parse_backtrace_line(line) ⇒ Object
Parse backtrace line into file path and line number.
- #pretty_exception_date(exception) ⇒ Object
-
#pretty_format(text) ⇒ Object
Rescue textilize call if RedCloth is not available.
-
#read_source_snippet(file_path, line_number, context: 5) ⇒ Object
Read source code snippet around a file:line.
-
#severity_for(exception) ⇒ Object
Severity badge class based on exception type.
- #sort_header_class(attribute) ⇒ Object
-
#sort_link(search, attribute, name = nil, **options, &block) ⇒ Object
Sort link helper for Ransack-compatible table headers.
Methods included from SourceCodeHelper
#resolve_source_path, #source_with_blame
Instance Method Details
#active_filter_pills ⇒ Object
Active filter pills for the filter bar
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 103 def active_filter_pills pills = [] if params[:q].present? params[:q].each do |key, value| next if value.blank? || key.to_s == "s" labels = { "exception_class_cont" => "Exception", "message_cont" => "Message", "message_or_exception_class_or_controller_name_or_action_name_cont" => "Search", "platform_eq" => "Platform", "priority_eq" => "Priority", "assigned_to_cont" => "Assigned to", "fingerprint_cont" => "Fingerprint", "occurrence_count_gteq" => "Minimum count" } label = labels[key.to_s] || key.to_s.sub(/_(cont|eq|gteq|lteq)$/, "").humanize pills << { label: label, value: value, group: :q, key: key.to_s } end end if params[:date_ranges_filter].present? value = { "1" => "Today", "3" => "Last 3 days", "7" => "Last 7 days", "30" => "Last 30 days" }[params[:date_ranges_filter].to_s] || "Custom" pills << { label: "Time", value: value, key: "date_ranges_filter" } end { "controller_actions_filter" => "Source", "status_filter" => "Status", "query" => "Search" }.each do |key, label| pills << { label: label, value: params[key], key: key } if params[key].present? end pills end |
#exception_occurrence_count(exception) ⇒ Object
154 155 156 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 154 def exception_occurrence_count(exception) exception.respond_to?(:occurrence_count) ? (exception.occurrence_count || 1) : 1 end |
#exception_searchable?(attribute) ⇒ Boolean
173 174 175 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 173 def exception_searchable?(attribute) LoggedException.ransackable_attributes.include?(attribute.to_s) end |
#exception_status(exception) ⇒ Object
158 159 160 161 162 163 164 165 166 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 158 def exception_status(exception) if exception.has_attribute?(:muted) && exception.muted? ["Muted", "muted"] elsif exception.has_attribute?(:snoozed_until) && exception.snoozed? ["Snoozed", "warning"] else ["Active", "success"] end end |
#exception_trend_data(days: 7) ⇒ Object
Simple sparkline data for stats
178 179 180 181 182 183 184 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 178 def exception_trend_data(days: 7) data = (0...days).reverse_each.map do |i| date = i.days.ago.to_date LoggedException.where(created_at: date.beginning_of_day..date.end_of_day).count end data end |
#filter_params_without(pill) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 141 def filter_params_without(pill) filters = params_filters.deep_stringify_keys if pill[:group] == :q filters["q"]&.delete(pill[:key]) filters.delete("q") if filters["q"].blank? else filters.delete(pill[:key]) end filters end |
#filtered? ⇒ Boolean
32 33 34 35 36 37 38 39 40 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 32 def filtered? legacy_filters = %i[ query date_ranges_filter exception_names_filter platform_filter controller_actions_filter status_filter ] ransack_filters = params[:q].respond_to?(:to_unsafe_h) ? params[:q].to_unsafe_h.except("s") : {} legacy_filters.any? { |name| params[name].present? } || ransack_filters.values.any?(&:present?) end |
#format_backtrace(backtrace, limit: nil) ⇒ Object
Format backtrace for display with optional collapse
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 73 def format_backtrace(backtrace, limit: nil) limit ||= RailsNexus.configuration.backtrace_limit lines = backtrace.to_s.split("\n") if lines.length > limit collapsed = lines[0...limit] remaining = lines[limit..] { visible: collapsed.join("\n"), hidden: remaining.join("\n"), hidden_count: remaining.length } else { visible: lines.join("\n"), hidden: nil, hidden_count: 0 } end end |
#git_blame_for_line(file_path, line_number, **_options) ⇒ Object
Get git blame for a file:line range
194 195 196 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 194 def git_blame_for_line(file_path, line_number, **) super(file_path, line_number) end |
#listify(text) ⇒ Object
42 43 44 45 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 42 def listify(text) list_items = text.scan(/^\s*\* (.+)/).map { |match| content_tag(:li, match.first) } content_tag(:ul, list_items) end |
#page_title(text) ⇒ Object
47 48 49 50 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 47 def page_title(text) title = [RailsNexus.application_name.presence, text].compact.join(" :: ") content_for(:title, title) end |
#parse_backtrace_line(line) ⇒ Object
Parse backtrace line into file path and line number
199 200 201 202 203 204 205 206 207 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 199 def parse_backtrace_line(line) return nil unless line.present? # Match formats: "file:line" or "file:line:in `method'" if line =~ /^(.+?):(\d+)(?::in `(.+?)')?$/ { file: $1, line: $2.to_i, method: $3 } else nil end end |
#pretty_exception_date(exception) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 6 def pretty_exception_date(exception) if RailsNexus.configuration.date_format return exception.created_at.strftime(RailsNexus.configuration.date_format) end time = exception.created_at diff = Time.current - time case when diff < 60 "#{(diff).to_i}s ago" when diff < 3600 "#{(diff / 60).to_i}m ago" when diff < 86400 "#{(diff / 3600).to_i}h ago" when diff < 604800 "#{(diff / 86400).to_i}d ago" when Date.today == time.to_date "Today, #{time.strftime('%I:%M %p')}" when Date.yesterday == time.to_date "Yesterday, #{time.strftime('%I:%M %p')}" else time.strftime('%b %d, %Y %I:%M %p') end end |
#pretty_format(text) ⇒ Object
Rescue textilize call if RedCloth is not available.
53 54 55 56 57 58 59 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 53 def pretty_format(text) begin textilize(text).html_safe rescue simple_format(text).html_safe end end |
#read_source_snippet(file_path, line_number, context: 5) ⇒ Object
Read source code snippet around a file:line
189 190 191 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 189 def read_source_snippet(file_path, line_number, context: 5) super(file_path, line_number, context_lines: context) end |
#severity_for(exception) ⇒ Object
Severity badge class based on exception type
91 92 93 94 95 96 97 98 99 100 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 91 def severity_for(exception) case exception.exception_class when /Timeout|Slow|Performance/i "warning" when /404|NotFound|Missing/i "info" else "danger" end end |
#sort_header_class(attribute) ⇒ Object
168 169 170 171 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 168 def sort_header_class(attribute) sort = @q&.sorts&.find { |item| item.name == attribute.to_s } ["sortable", ("sorted-#{sort.dir}" if sort)].compact.join(" ") end |
#sort_link(search, attribute, name = nil, **options, &block) ⇒ Object
Sort link helper for Ransack-compatible table headers.
62 63 64 65 66 67 68 69 70 |
# File 'app/helpers/rails_nexus/logged_exceptions_helper.rb', line 62 def sort_link(search, attribute, name = nil, **, &block) name ||= attribute.to_s.humanize if defined?(Ransack) && search.respond_to?(:result) Ransack::Helpers::FormHelper.instance_method(:sort_link).bind(self).call(search, attribute, name, **, &block) else link_to name, "#", **, &block end end |