2020-12-07 16:21:46 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# Procesa los errores de JavaScript
|
|
|
|
class BacktraceJob < ApplicationJob
|
|
|
|
queue_as :low_priority
|
|
|
|
|
2020-12-07 18:27:24 +00:00
|
|
|
attr_reader :params, :site_id
|
2020-12-07 16:21:46 +00:00
|
|
|
|
2020-12-07 18:27:24 +00:00
|
|
|
def perform(site_id:, params:)
|
2020-12-07 16:36:09 +00:00
|
|
|
@site_id = site_id
|
2020-12-07 18:27:24 +00:00
|
|
|
@params = params
|
2020-12-07 16:21:46 +00:00
|
|
|
|
2020-12-07 16:36:09 +00:00
|
|
|
return if files.empty?
|
|
|
|
|
2020-12-07 18:27:24 +00:00
|
|
|
params['errors'].each do |error|
|
2020-12-07 16:21:46 +00:00
|
|
|
error['backtrace'].each do |backtrace|
|
|
|
|
offset = SourceMap::Offset.new(backtrace['line'], backtrace['column'])
|
|
|
|
mapping = sourcemap.bsearch(offset)
|
|
|
|
|
|
|
|
next unless mapping
|
|
|
|
|
|
|
|
backtrace['file'] = mapping.source
|
|
|
|
backtrace['line'] = mapping.original.line
|
|
|
|
backtrace['column'] = mapping.original.column
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
|
|
|
raise NoMethodError
|
|
|
|
rescue NoMethodError => e
|
2020-12-07 18:27:24 +00:00
|
|
|
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params })
|
2020-12-07 16:21:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2020-12-07 16:36:09 +00:00
|
|
|
def site
|
|
|
|
@site ||= Site.find(site_id)
|
|
|
|
end
|
|
|
|
|
2020-12-07 16:21:46 +00:00
|
|
|
# Obtiene todos los archivos del backtrace
|
|
|
|
def files
|
2020-12-08 21:51:41 +00:00
|
|
|
@files ||= params['errors'].map { |x| x['backtrace'] }.flatten.map { |x| x['file'].split('@').last }.uniq.select { |x| x&.start_with?(site.url) }
|
2020-12-07 16:21:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Asume que todos los sourcemaps comparten la misma URL, lo
|
|
|
|
# correcto sería buscarlo en sourceMappingURL al final de cada
|
|
|
|
# archivo.
|
|
|
|
#
|
|
|
|
# Descarga los archivos y obtiene el backtrace original.
|
|
|
|
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
|
|
|
|
rescue Down::Error, FastJsonparser::Error
|
|
|
|
SourceMap::Map.new
|
|
|
|
end.reduce(&:+)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|