class Anyway::Tracing::Trace

Constants

UNDEF

Attributes

source[R]
type[R]
value[R]

Public Class Methods

accessor_source(location) click to toggle source
# File lib/anyway/tracing.rb, line 170
def accessor_source(location)
  {type: :accessor, called_from: location.path_lineno}
end
capture() { || ... } click to toggle source
# File lib/anyway/tracing.rb, line 131
def capture
  unless Settings.tracing_enabled
    yield
    return
  end

  trace = Trace.new
  trace_stack.push trace
  yield
  trace_stack.last
ensure
  trace_stack.pop
end
current_trace() click to toggle source
# File lib/anyway/tracing.rb, line 149
  def current_trace() = trace_stack.last

  alias_method :tracing?, :current_trace

  def source_stack
    (Thread.current[:__anyway__trace_source_stack__] ||= [])
  end

  def current_trace_source
    source_stack.last || accessor_source(caller_locations(2, 1).first)
  end

  def with_trace_source(src)
    source_stack << src
    yield
  ensure
    source_stack.pop
  end

  private

  def accessor_source(location)
    {type: :accessor, called_from: location.path_lineno}
  end
end
current_trace_source() click to toggle source
# File lib/anyway/tracing.rb, line 157
def current_trace_source
  source_stack.last || accessor_source(caller_locations(2, 1).first)
end
new(type = :trace, value = UNDEF, **source) click to toggle source
# File lib/anyway/tracing.rb, line 19
def initialize(type = :trace, value = UNDEF, **source)
  @type = type
  @source = source
  @value = (value == UNDEF) ? Hash.new { |h, k| h[k] = Trace.new(:trace) } : value
end
source_stack() click to toggle source
# File lib/anyway/tracing.rb, line 153
def source_stack
  (Thread.current[:__anyway__trace_source_stack__] ||= [])
end
trace!(type, *path, **) { || ... } click to toggle source
# File lib/anyway/tracing.rb, line 177
def trace!(type, *path, **)
  return yield unless Tracing.tracing?
  val = yield
  if val.is_a?(Hash)
    Tracing.current_trace.merge_values(val, type:, **)
  elsif !path.empty?
    Tracing.current_trace.record_value(val, *path, type:, **)
  end
  val
end
trace_stack() click to toggle source
# File lib/anyway/tracing.rb, line 145
def trace_stack
  (Thread.current[:__anyway__trace_stack__] ||= [])
end
with_trace_source(src) { || ... } click to toggle source
# File lib/anyway/tracing.rb, line 161
def with_trace_source(src)
  source_stack << src
  yield
ensure
  source_stack.pop
end

Public Instance Methods

clear() click to toggle source
# File lib/anyway/tracing.rb, line 81
    def clear() = value.clear

    def trace?() = type == :trace

    def to_h
      if trace?
        value.transform_values(&:to_h).tap { it.default_proc = nil }
      else
        {value:, source:}
      end
    end

    def dup() = self.class.new(type, value.dup, **source)

    def pretty_print(q)
      if trace?
        q.nest(2) do
          q.breakable ""
          q.seplist(value, nil, :each) do |k, v|
            q.group do
              q.text k
              q.text " =>"
              if v.trace?
                q.text " { "
                q.pp v
                q.breakable " "
                q.text "}"
              else
                q.breakable " "
                q.pp v
              end
            end
          end
        end
      else
        q.pp value
        q.group(0, " (", ")") do
          q.seplist(source, lambda { q.breakable " " }, :each) do |k, v|
            q.group do
              q.text k.to_s
              q.text "="
              q.text v.to_s
            end
          end
        end
      end
    end
  end

  class << self
    def capture
      unless Settings.tracing_enabled
        yield
        return
      end

      trace = Trace.new
      trace_stack.push trace
      yield
      trace_stack.last
    ensure
      trace_stack.pop
    end

    def trace_stack
      (Thread.current[:__anyway__trace_stack__] ||= [])
    end

    def current_trace() = trace_stack.last

    alias_method :tracing?, :current_trace

    def source_stack
      (Thread.current[:__anyway__trace_source_stack__] ||= [])
    end

    def current_trace_source
      source_stack.last || accessor_source(caller_locations(2, 1).first)
    end

    def with_trace_source(src)
      source_stack << src
      yield
    ensure
      source_stack.pop
    end

    private

    def accessor_source(location)
      {type: :accessor, called_from: location.path_lineno}
    end
  end

  module_function

  def trace!(type, *path, **)
    return yield unless Tracing.tracing?
    val = yield
    if val.is_a?(Hash)
      Tracing.current_trace.merge_values(val, type:, **)
    elsif !path.empty?
      Tracing.current_trace.record_value(val, *path, type:, **)
    end
    val
  end
end
dig(...) click to toggle source
# File lib/anyway/tracing.rb, line 25
def dig(...)
  value.dig(...)
end
dup() click to toggle source
# File lib/anyway/tracing.rb, line 93
  def dup() = self.class.new(type, value.dup, **source)

  def pretty_print(q)
    if trace?
      q.nest(2) do
        q.breakable ""
        q.seplist(value, nil, :each) do |k, v|
          q.group do
            q.text k
            q.text " =>"
            if v.trace?
              q.text " { "
              q.pp v
              q.breakable " "
              q.text "}"
            else
              q.breakable " "
              q.pp v
            end
          end
        end
      end
    else
      q.pp value
      q.group(0, " (", ")") do
        q.seplist(source, lambda { q.breakable " " }, :each) do |k, v|
          q.group do
            q.text k.to_s
            q.text "="
            q.text v.to_s
          end
        end
      end
    end
  end
end
keep_if(...) click to toggle source
# File lib/anyway/tracing.rb, line 76
def keep_if(...)
  raise ArgumentError, "You can only filter :trace type, and this is :#{type}" unless trace?
  value.keep_if(...)
end
merge!(another_trace) click to toggle source
# File lib/anyway/tracing.rb, line 63
def merge!(another_trace)
  raise ArgumentError, "You can only merge into a :trace type, and this is :#{type}" unless trace?
  raise ArgumentError, "You can only merge a :trace type, but trying :#{type}" unless another_trace.trace?

  another_trace.value.each do |key, sub_trace|
    if sub_trace.trace?
      value[key].merge! sub_trace
    else
      value[key] = sub_trace
    end
  end
end
merge_values(hash, **opts) click to toggle source
# File lib/anyway/tracing.rb, line 43
def merge_values(hash, **opts)
  return hash unless hash

  hash.each do |key, val|
    if val.is_a?(Hash)
      value[key.to_s].merge_values(val, **opts)
    else
      value[key.to_s] = Trace.new(:value, val, **opts)
    end
  end

  hash
end
pretty_print(q) click to toggle source
# File lib/anyway/tracing.rb, line 95
def pretty_print(q)
  if trace?
    q.nest(2) do
      q.breakable ""
      q.seplist(value, nil, :each) do |k, v|
        q.group do
          q.text k
          q.text " =>"
          if v.trace?
            q.text " { "
            q.pp v
            q.breakable " "
            q.text "}"
          else
            q.breakable " "
            q.pp v
          end
        end
      end
    end
  else
    q.pp value
    q.group(0, " (", ")") do
      q.seplist(source, lambda { q.breakable " " }, :each) do |k, v|
        q.group do
          q.text k.to_s
          q.text "="
          q.text v.to_s
        end
      end
    end
  end
end
record_key(key, key_trace) click to toggle source
# File lib/anyway/tracing.rb, line 57
def record_key(key, key_trace)
  @value = Hash.new { |h, k| h[k] = Trace.new(:trace) } unless value.is_a?(::Hash)

  value[key] = key_trace
end
record_value(val, *path, **opts) click to toggle source
# File lib/anyway/tracing.rb, line 29
def record_value(val, *path, **opts)
  key = path.pop
  trace = if val.is_a?(Hash)
    Trace.new.tap { it.merge_values(val, **opts) }
  else
    Trace.new(:value, val, **opts)
  end

  target_trace = path.empty? ? self : value.dig(*path)
  target_trace.record_key(key.to_s, trace)

  val
end
to_h() click to toggle source
# File lib/anyway/tracing.rb, line 85
def to_h
  if trace?
    value.transform_values(&:to_h).tap { it.default_proc = nil }
  else
    {value:, source:}
  end
end
trace?() click to toggle source
# File lib/anyway/tracing.rb, line 83
      def trace?() = type == :trace

      def to_h
        if trace?
          value.transform_values(&:to_h).tap { it.default_proc = nil }
        else
          {value:, source:}
        end
      end

      def dup() = self.class.new(type, value.dup, **source)

      def pretty_print(q)
        if trace?
          q.nest(2) do
            q.breakable ""
            q.seplist(value, nil, :each) do |k, v|
              q.group do
                q.text k
                q.text " =>"
                if v.trace?
                  q.text " { "
                  q.pp v
                  q.breakable " "
                  q.text "}"
                else
                  q.breakable " "
                  q.pp v
                end
              end
            end
          end
        else
          q.pp value
          q.group(0, " (", ")") do
            q.seplist(source, lambda { q.breakable " " }, :each) do |k, v|
              q.group do
                q.text k.to_s
                q.text "="
                q.text v.to_s
              end
            end
          end
        end
      end
    end

    class << self
      def capture
        unless Settings.tracing_enabled
          yield
          return
        end

        trace = Trace.new
        trace_stack.push trace
        yield
        trace_stack.last
      ensure
        trace_stack.pop
      end

      def trace_stack
        (Thread.current[:__anyway__trace_stack__] ||= [])
      end

      def current_trace() = trace_stack.last

      alias_method :tracing?, :current_trace

      def source_stack
        (Thread.current[:__anyway__trace_source_stack__] ||= [])
      end

      def current_trace_source
        source_stack.last || accessor_source(caller_locations(2, 1).first)
      end

      def with_trace_source(src)
        source_stack << src
        yield
      ensure
        source_stack.pop
      end

      private

      def accessor_source(location)
        {type: :accessor, called_from: location.path_lineno}
      end
    end

    module_function

    def trace!(type, *path, **)
      return yield unless Tracing.tracing?
      val = yield
      if val.is_a?(Hash)
        Tracing.current_trace.merge_values(val, type:, **)
      elsif !path.empty?
        Tracing.current_trace.record_value(val, *path, type:, **)
      end
      val
    end
  end
end