module Traject::Util

Just some internal utility methods

Public Class Methods

backtrace_from_config(file_path, exception) click to toggle source

Extract just the part of the backtrace that is “below” the config file mentioned. If we can't find the config file in the stack trace, we might return empty array.

If the ruby supports Exception#backtrace_locations, the returned array will actually be of Thread::Backtrace::Location elements.

# File lib/traject/util.rb, line 84
def self.backtrace_from_config(file_path, exception)
  filtered_trace = []
  found          = false

  # MRI 2.1+ has exception.backtrace_locations which makes
  # this a lot easier, but JRuby 1.7.x doesn't yet, so we
  # need to do it both ways.
  if (exception.respond_to?(:backtrace_locations) &&
      exception.backtrace_locations &&
      exception.backtrace_locations.length > 0)

    exception.backtrace_locations.each do |location|
      filtered_trace << location
      (found=true and break) if location.path == file_path
    end
  else
    filtered_trace = []
    exception.backtrace.each do |line|
      filtered_trace << line
      (found=true and break) if line.start_with?(file_path)
    end
  end

  return found ? filtered_trace : []
end
backtrace_lineno_for_config(file_path, exception) click to toggle source

Provide a config source file path, and an exception.

Returns the line number from the first line in the stack trace of the exception that matches your file path. of the first line in the backtrace matching that file_path.

Returns `nil` if no suitable backtrace line can be found.

Has special logic to try and grep the info out of a SyntaxError, bah.

# File lib/traject/util.rb, line 43
def self.backtrace_lineno_for_config(file_path, exception)
  # For a SyntaxError, we really need to grep it from the
  # exception message, it really appears to be nowhere else. Ugh.
  if exception.kind_of? SyntaxError
    if m = /:(\d+):/.match(exception.message)
      return m[1].to_i
    end
  end

  # Otherwise we try to fish it out of the backtrace, first
  # line matching the config file path.

  # exception.backtrace_locations exists in MRI 2.1+, which makes
  # our task a lot easier. But not yet in JRuby 1.7.x, so we got to
  # handle the old way of having to parse the strings in backtrace too.
  if (exception.respond_to?(:backtrace_locations) &&
      exception.backtrace_locations &&
      exception.backtrace_locations.length > 0)
    location = exception.backtrace_locations.find do |bt|
      bt.path == file_path
    end
    return location ? location.lineno : nil
  else # have to parse string backtrace
    exception.backtrace.each do |line|
      if line.start_with?(file_path)
        if m = /\A.*\:(\d+)\:in/.match(line)
          return m[1].to_i
        end
      end
    end
    # if we got here, we have nothing
    return nil
  end
end
drain_queue(queue) click to toggle source

Ruby stdlib queue lacks a 'drain' function, we write one.

Removes everything currently in the ruby stdlib queue, and returns it an array. Should be concurrent-safe, but queue may still have some things in it after drain, if there are concurrent writers.

# File lib/traject/util.rb, line 116
def self.drain_queue(queue)
  result = []

  queue_size = queue.size
  begin
    queue_size.times do
      result << queue.deq(:raise_if_empty)
    end
  rescue ThreadError
    # Need do nothing, queue was concurrently popped, no biggie, but let's
    # stop iterating and return what we've got.
    return result
  end

  return result
end
exception_to_log_message(e) click to toggle source
# File lib/traject/util.rb, line 5
def self.exception_to_log_message(e)
  indent = "    "

  msg = indent + "Exception: " + e.class.name + ": " + e.message + "\n"
  msg += indent + e.backtrace.first + "\n"

  caused_by = e.cause
  # JRuby Java exception might have getRootCause
  if caused_by == nil && e.respond_to?(:getRootCause) && e.getRootCause
    caused_by = e.getRootCause
  end
  if caused_by == e
    caused_by = nil
  end
  if caused_by
    msg       += indent + "Caused by\n"
    msg       += indent + caused_by.class.name + ": " + caused_by.message + "\n"
    msg       += indent + caused_by.backtrace.first + "\n"
  end

  return msg
end
extract_caller_location(str) click to toggle source

From ruby caller method, you get an array. Pass one line of the array here, get just file and line number out.

# File lib/traject/util.rb, line 30
def self.extract_caller_location(str)
  str.split(':in `').first
end
io_name(io_like_object) click to toggle source

How can we refer to an io object input in logs? For now, if it's a file-like object, we can use path.

# File lib/traject/util.rb, line 141
def self.io_name(io_like_object)
  io_like_object.path if io_like_object.respond_to?(:path)
end
is_jruby?() click to toggle source
# File lib/traject/util.rb, line 133
def self.is_jruby?
  unless defined?(@is_jruby)
    @is_jruby = defined?(JRUBY_VERSION)
  end
  @is_jruby
end