diff --git a/app/jobs/backtrace_job.rb b/app/jobs/backtrace_job.rb index b7c4ab90..fa8ee790 100644 --- a/app/jobs/backtrace_job.rb +++ b/app/jobs/backtrace_job.rb @@ -12,7 +12,7 @@ class BacktraceJob < ApplicationJob @site_id = site_id @params = params - unless files.empty? + unless sources.empty? params['errors'].each do |error| error['backtrace'].each do |backtrace| offset = SourceMap::Offset.new(backtrace['line'], backtrace['column']) @@ -20,9 +20,15 @@ class BacktraceJob < ApplicationJob next unless mapping + data = data(backtrace['file']) + backtrace['file'] = mapping.source backtrace['line'] = mapping.original.line backtrace['column'] = mapping.original.column + + # Encuentra el código fuente del error + source = data.dig('sourcesContent', data['sources']&.index(backtrace['file']))&.split("\n") + backtrace['function'] = source.dig(backtrace['line'] - 1) if source.present? end end end @@ -40,15 +46,33 @@ class BacktraceJob < ApplicationJob @site ||= Site.find_by_id(site_id) end - # Obtiene todos los archivos del backtrace - def files - @files ||= params['errors'].map do |x| - x['backtrace'] - end.flatten.map do |x| - x['file'].split('@').last - end.uniq.select do |x| - x&.start_with?(site.url) - end + # Obtiene todos los archivos del backtrace solo si los puede descargar + # desde fuentes seguras. + # + # XXX: Idealmente no trabajamos con recursos externos, pero en este + # momento no podemos saber todas las URLs de un sitio y quizás nunca + # lo sabremos :B + def sources + @sources ||= params['errors'].map do |x| + x['backtrace'] + end.flatten.map do |x| + x['file'].split('@').last + end.uniq.select do |x| + %r{\Ahttps://} =~ x + end + end + + # Descarga y devuelve los datos de un archivo + # + # @param [String] La URL del map + # @return [Hash] + def data(map) + map += '.map' unless map.end_with? '.map' + + @data ||= {} + @data[map] ||= FastJsonparser.parse(Rails.cache.fetch(map, expires_in: 12.hours) do + Down.open(map).read + end, symbolize_keys: false) end # Asume que todos los sourcemaps comparten la misma URL, lo @@ -56,15 +80,13 @@ class BacktraceJob < ApplicationJob # archivo. # # Descarga los archivos y obtiene el backtrace original. + # + # @return [SourceMap::Map] def sourcemap @sourcemap ||= begin - files.map { |x| "#{x}.map" }.map do |x| - data = FastJsonparser.parse(Rails.cache.fetch(x, expires_in: 12.hours) do - Down.open(x).read - end, symbolize_keys: false) - - SourceMap::Map.from_hash data + sources.map { |x| "#{x}.map" }.map do |map| + SourceMap::Map.from_hash data(map) rescue Down::Error, FastJsonparser::Error SourceMap::Map.new end.reduce(&:+)