Module: RailsErrorDashboard::BacktraceHelper

Defined in:
app/helpers/rails_error_dashboard/backtrace_helper.rb

Constant Summary collapse

LANGUAGE_MAP =

Language mapping for syntax highlighting

{
  ".rb" => "ruby",
  ".js" => "javascript",
  ".jsx" => "javascript",
  ".ts" => "typescript",
  ".tsx" => "typescript",
  ".erb" => "erb",
  ".html" => "html",
  ".htm" => "html",
  ".css" => "css",
  ".scss" => "scss",
  ".sass" => "scss",
  ".yml" => "yaml",
  ".yaml" => "yaml",
  ".json" => "json",
  ".sql" => "sql",
  ".xml" => "xml",
  ".py" => "python",
  ".go" => "go",
  ".java" => "java",
  ".c" => "c",
  ".cpp" => "cpp",
  ".h" => "c",
  ".hpp" => "cpp",
  ".sh" => "bash",
  ".bash" => "bash",
  ".zsh" => "bash",
  ".php" => "php",
  ".pl" => "perl",
  ".r" => "r",
  ".rs" => "rust",
  ".swift" => "swift",
  ".kt" => "kotlin",
  ".scala" => "scala",
  ".clj" => "clojure",
  ".ex" => "elixir",
  ".exs" => "elixir"
}.freeze

Instance Method Summary collapse

Instance Method Details

#detect_language_from_path(file_path) ⇒ Object

Detect programming language from file path Returns Highlight.js language identifier



52
53
54
55
56
57
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 52

def detect_language_from_path(file_path)
  return "plaintext" unless file_path

  ext = File.extname(file_path).downcase
  LANGUAGE_MAP[ext] || "plaintext"
end

#filter_app_code(frames) ⇒ Object

Filter to show only application code



60
61
62
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 60

def filter_app_code(frames)
  frames.select { |f| f[:category] == :app }
end

#filter_framework_code(frames) ⇒ Object

Filter to show framework/gem code



65
66
67
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 65

def filter_framework_code(frames)
  frames.reject { |f| f[:category] == :app }
end

#frame_bg_class(category) ⇒ Object

Get background color class for frame Uses Catppuccin-themed backtrace frame classes from _components.scss



103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 103

def frame_bg_class(category)
  case category
  when :app
    "backtrace-frame frame-app"
  when :gem
    "backtrace-frame frame-gem"
  when :framework
    "backtrace-frame frame-framework"
  when :ruby_core
    "backtrace-frame frame-ruby-core"
  else
    ""
  end
end

#frame_category_name(category) ⇒ Object

Format category name



119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 119

def frame_category_name(category)
  case category
  when :app
    "Your Code"
  when :gem
    "Gem"
  when :framework
    "Rails Framework"
  when :ruby_core
    "Ruby Core"
  else
    "Unknown"
  end
end

#frame_color_class(category) ⇒ Object

Get color class for frame category



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 86

def frame_color_class(category)
  case category
  when :app
    "text-success fw-bold"
  when :gem
    "text-info"
  when :framework
    "text-warning"
  when :ruby_core
    "text-secondary"
  else
    "text-muted"
  end
end

#frame_count_by_category(frames) ⇒ Object

Count frames by category



135
136
137
138
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 135

def frame_count_by_category(frames)
  frames.group_by { |f| f[:category] }
        .transform_values(&:count)
end

#frame_icon(category) ⇒ Object

Get icon for frame category



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 70

def frame_icon(category)
  case category
  when :app
    '<i class="bi bi-code-square text-success"></i>'.html_safe
  when :gem
    '<i class="bi bi-box text-info"></i>'.html_safe
  when :framework
    '<i class="bi bi-gear text-warning"></i>'.html_safe
  when :ruby_core
    '<i class="bi bi-gem text-secondary"></i>'.html_safe
  else
    '<i class="bi bi-question-circle text-muted"></i>'.html_safe
  end
end

Generate GitHub/GitLab/Bitbucket link for a frame Returns URL string or nil



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 190

def generate_repository_link(frame, error_log)
  return nil unless RailsErrorDashboard.configuration.enable_source_code_integration
  return nil unless RailsErrorDashboard.configuration.git_repository_url.present?
  return nil unless frame[:file_path] && frame[:line_number]

  repo_url = RailsErrorDashboard.configuration.git_repository_url
  commit_sha = determine_commit_sha(error_log)

  generator = Services::GithubLinkGenerator.new(
    repository_url: repo_url,
    file_path: frame[:file_path],
    line_number: frame[:line_number],
    commit_sha: commit_sha
  )

  generator.generate_link
end

#parse_backtrace(backtrace_string) ⇒ Object

Parse backtrace string into structured frames



46
47
48
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 46

def parse_backtrace(backtrace_string)
  Services::BacktraceParser.parse(backtrace_string)
end

#read_git_blame(frame) ⇒ Object

Read git blame for a backtrace frame Returns blame data hash or nil



173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 173

def read_git_blame(frame)
  return nil unless RailsErrorDashboard.configuration.enable_source_code_integration
  return nil unless RailsErrorDashboard.configuration.enable_git_blame
  return nil unless frame[:file_path] && frame[:line_number]

  # Cache key includes file path and line number
  cache_key = "git_blame/#{frame[:file_path]}/#{frame[:line_number]}"
  cache_ttl = RailsErrorDashboard.configuration.source_code_cache_ttl || 3600

  Rails.cache.fetch(cache_key, expires_in: cache_ttl) do
    reader = Services::GitBlameReader.new(frame[:file_path], frame[:line_number])
    reader.read_blame
  end
end

#read_source_code(frame, context: 5) ⇒ Object

Read source code for a backtrace frame Returns hash with { lines:, error: } or nil



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'app/helpers/rails_error_dashboard/backtrace_helper.rb', line 142

def read_source_code(frame, context: 5)
  return nil unless RailsErrorDashboard.configuration.enable_source_code_integration
  return nil unless frame[:file_path] && frame[:line_number]

  # Cache key includes file path, line number, and git SHA if available
  cache_key = "source_code/#{frame[:file_path]}/#{frame[:line_number]}"
  cache_ttl = RailsErrorDashboard.configuration.source_code_cache_ttl || 3600

  Rails.cache.fetch(cache_key, expires_in: cache_ttl) do
    context_lines = RailsErrorDashboard.configuration.source_code_context_lines || 5
    reader = Services::SourceCodeReader.new(frame[:file_path], frame[:line_number])
    lines = reader.read_lines(context: context_lines)

    if lines
      {
        lines: lines,
        language: detect_language_from_path(frame[:file_path]),
        error: nil
      }
    else
      {
        lines: nil,
        language: nil,
        error: reader.error
      }
    end
  end
end