GithubHelp home page GithubHelp logo

st0012 / object_tracer Goto Github PK

View Code? Open in Web Editor NEW
447.0 14.0 13.0 1.47 MB

ObjectTracer tracks objects and records their activities

License: MIT License

Ruby 99.67% Shell 0.19% Makefile 0.14%
ruby rubygem rails ruby-on-rails debugging-tool debugging tracepoints trace tracing object-oriented-tracing

object_tracer's Introduction

Hi there! πŸ‘‹ I'm a developer who's passionate about building developer tooling to help improve productivity and make code-writing more enjoyable for everyone. Here are a few of the projects I'm currently involved in:

  • πŸ› οΈ Maintainer of Ruby's IRB and Reline libraries
  • πŸš€ Major contributor of Ruby's debugger ruby/debug
  • πŸ’Ό At Shopify, I work on the ruby-lsp project and its ruby-lsp-rails extension
  • πŸ“¦ I also maintain Sentry's Ruby library sentry-ruby

Feel free to check out some of the projects I've been working on:

ruby-lsp Card ruby-lsp-rails Card
debug Card ruby/irb Card
reline Card sentry-ruby Card

object_tracer's People

Contributors

dependabot[bot] avatar meganemura avatar nickwarm avatar skade avatar st0012 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

object_tracer's Issues

Support limiting tracing helper's scope

With a Block

print_calls_in_detail(ActionDispatch::Http::URL) do
  ActionDispatch::Http::URL.url_for(host: "www.ror.co.uk", subdomain: "api", tld_length: 2)
end

# ignore what happens outside the block

With stop_tracing

print_calls_in_detail(ActionDispatch::Http::URL)
result = ActionDispatch::Http::URL.url_for(host: "www.ror.co.uk", subdomain: "api", tld_length: 2)

stop_tracing # ignore what happens after this line

Add with_print_calls method

Sometimes it's annoying to break a series of methods chain into several lines, just to call print_calls on an object. For example:

# we need to change this
SomeService.new(params).do_something

# into

s = SomeService.new(params)
print_calls(s)
s.do_something

For such cases, I'd like to add .with_print_calls method to the Object class. Then we can do

SomeService.new(params).with_print_calls.do_something

Provide options for tapping on call or return events

Right now it only listens to return events, which makes it possible to get a method call's return value but method calls' order may look confusing.
It should allow users to choose if they want to listen to call events instead. If the user doesn't need return_value and cares about calls' order more, he/she should be able to do it.

Add tap_on_mutation!

tap_on_mutation! can track method calls that change certain object's state, e.g. updating instance variables. This can be very useful for certain cases.

However, for objects like AR records, we need to provide a way to specify what internal states to track (maybe just attributes).

Support tracking ActiveRecord::Base instances by their ids

Currently, we track objects with their object_id. But for ActiveRecord::Base's instances, we can track them with record's id. This will allow us to track records from different places and don't need to trace where the object's initialized.

InitializationTracker's logic can cause error

Not every class respond to ancestors method.

      # InitializationTracker
      def filter_condition_satisfied?(tp)
        receiver = tp.self
        method_name = tp.callee_id

        if target.ancestors.include?(ActiveRecord::Base)
          method_name == :new && receiver.ancestors.include?(target)
        else
          method_name == :initialize && receiver.is_a?(target)
        end
      end

Global Configuration

Adding options in every helper call can by annoying, we should have something like

TappingDevice.config[:exclude_by_paths] = [/gems/]
TappingDevice.config[:with_traces_to] = 10

Support write_* helpers

print_* helpers prints the output to stdout directly, which can be hard to read when mixed with other log outputs. So we should also support write_* helpers that write all output into a designated file (default should be something like /tmp/tapping_device.log). And then users can do tail -f /tmp/tapping_device.log or cat /tmp/tapping_device.log with cleaner information.

write_calls(object)
write_traces(object)
write_mutations(object)

Support tag option

Sometimes we'll tap multiple objects at the same time and it'll be very useful to add tag to the payload/output messages to help determine the target. for example:

print_calls(seat_assignment_1, tag: "left assignment")
print_calls(seat_assignment_2, tag: "right assignment")
:x [left assignment] # SeatAssignment::GeneratedAttributeMethods
    from: /app/models/seat_picker.rb:228
    <= {}
    => 0

:x [right assignment] # SeatAssignment::GeneratedAttributeMethods
    from: /app/models/seat_picker.rb:230
    <= {}
    => 10

inspect:true not working for activerecord

:mutations_from_database (private) # ActiveModel::Dirty
from: /var/lib/gems/2.7.0/gems/activerecord-6.0.3.4/lib/active_record/attribute_methods/dirty.rb:161
changes:
@mutations_from_database: [undefined] =>
#ActiveModel::AttributeMutationTracker:0x00007f9ee9963040

my questions:

  1. how to make #ActiveModel::AttributeMutationTracker:0x00007f9ee9963040 to be inspect, (looks like inspect: true) not working?
  2. whats best practise to trace one field of the ActiveModel

Rename to ObjectTracer?

TappingDevice doesn't convey the idea of the gem very well. But ObjectTracer seems to be a very good name for that purpose.

Add with_internal_states option

Besides arguments, sometimes internal states will affect a method's result too. But currently print_calls doesn't contain such information. So in such cases, users still need to dig into the method to check internal states.

Sample output:

:update? # CartOperationsService::OperationSet
    from: /Users/st0012/projects/ticketsolve/app/services/cart_operations_service.rb:102
    states:
     @price: 10.0
    <= {args: [], block: nil}
    => true

Add ignore_private option

Assume we have a class like:

class Operation
  def extras
    dig_attribute("extras")
  end

  private

  def data
    @data
  end

  def dig_attribute(attr)
    data.dig("attributes", attr) 
  end
end

Every time we call extras, it'll call dig_attribute and data as well. So the output of print_calls(operation) would look like this

ζˆͺεœ– 2020-06-21 δΈ‹εˆ4 44 27

As you can see, the entries of private helpers like data and dig_attribute provide duplicated or redundant information.

So we should have an option to filter out calls of private helpers.

print_calls(operation, ignore_private: true)

Tapping any instance of class

Hello.

Some additional methods (or options) would be helpful for tapping any instances of specific class.

Example: print_calls_of_any_instance(MyClass).

Handful for cases when you can't access all objects, like internal work of ORM, or it'd be ugly.

Don't tap on the same object repeatedly

It should be smart enough to tap on an unique instance just once, especially in a Rails application where files will be auto-reloaded.

class PostsController
  print_instance_traces(self)
end

Filter Out Entries From TappingDevice

When using something like

print_calls(self)

It prints the print_calls call. Which should be filtered out

:print_calls # TappingDevice::Trackable
    from: /Users/st0012/projects/ticketsolve/app/controllers/api/ticketoffice/v1/view_download_options_controller.rb:6
    <= {target: #<Api::Ticketoffice::V1::ViewDownloadOptionsController:0x00007fc667e63f90>, options: {filter_by_paths: [], exclude_by_paths: [], with_trace_to: 50, root_device: #<TappingDevice:0x00007fc667f0b0d8>, event_type: return, descendants: [], track_as_records: false}}
    => #<TappingDevice:0x00007fc667f0b0d8>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.