{"id":13878510,"url":"https://github.com/ruby/tracer","last_synced_at":"2025-04-13T05:08:24.822Z","repository":{"id":34841664,"uuid":"138372451","full_name":"ruby/tracer","owner":"ruby","description":"Outputs a source level execution trace of a Ruby program.","archived":false,"fork":false,"pushed_at":"2024-05-04T13:14:39.000Z","size":222,"stargazers_count":84,"open_issues_count":2,"forks_count":10,"subscribers_count":32,"default_branch":"master","last_synced_at":"2025-04-13T05:08:21.260Z","etag":null,"topics":["ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruby.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-23T04:54:57.000Z","updated_at":"2025-04-09T00:01:49.000Z","dependencies_parsed_at":"2024-05-04T14:23:39.964Z","dependency_job_id":"df1cdfe3-f713-4e5c-ac16-07e51dfc61de","html_url":"https://github.com/ruby/tracer","commit_stats":{"total_commits":86,"total_committers":21,"mean_commits":4.095238095238095,"dds":0.6627906976744187,"last_synced_commit":"3636d63d1487a472ee99470a9d38ebfc166a88f5"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby%2Ftracer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby%2Ftracer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby%2Ftracer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby%2Ftracer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruby","download_url":"https://codeload.github.com/ruby/tracer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665747,"owners_count":21142123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ruby"],"created_at":"2024-08-06T08:01:51.807Z","updated_at":"2025-04-13T05:08:24.795Z","avatar_url":"https://github.com/ruby.png","language":"Ruby","readme":"# Tracer\n\n[![Ruby](https://github.com/ruby/tracer/actions/workflows/main.yml/badge.svg)](https://github.com/ruby/tracer/actions/workflows/main.yml)\n[![Gem Version](https://badge.fury.io/rb/tracer.svg)](https://badge.fury.io/rb/tracer)\n\nThe `tracer` gem provides helpful tracing utilities to help users observe their program's runtime behaviour.\n\nThe currently supported tracers are:\n\n- [`ObjectTracer`](#objecttracer)\n- [`IvarTracer`](#ivartracer)\n- [`CallTracer`](#calltracer)\n- [`ExceptionTracer`](#exceptiontracer)\n- [`LineTracer`](#linetracer)\n\nIt also comes with experimental [IRB integration](#irb-integration) to allow quick access from REPL.\n\n## Installation\n\n```shell\n$ bundle add tracer --group=development,test\n```\n\nOr directly add it to your `Gemfile`\n\n```rb\ngroup :development, :test do\n  gem \"tracer\"\nend\n```\n\nIf bundler is not being used to manage dependencies, install the gem by executing:\n\n```shell\n$ gem install tracer\n```\n\n## Usage\n\n```rb\nTracer.trace(object) { ... } # trace object's activities in the given block\nTracer.trace_call { ... } # trace method calls in the given block\nTracer.trace_exception { ... } # trace exceptions in the given block\n```\n\n**Example**\n\n```rb\nrequire \"tracer\"\n\nobj = Object.new\n\ndef obj.foo\n  100\nend\n\ndef bar(obj)\n  obj.foo\nend\n\nTracer.trace(obj) { bar(obj) }\n #depth:1  #\u003cObject:0x000000010903c190\u003e is used as a parameter obj of Object#bar at test.rb:13:in `block in \u003cmain\u003e'\n #depth:2  #\u003cObject:0x000000010903c190\u003e receives .foo at test.rb:10:in `bar'\n```\n\n### `tracer/helper`\n\nIf you want to avoid the `Tracer` namespace, you can do `require \"tracer/helper\"` instead:\n\n```rb\nrequire \"tracer/helper\"\n\ntrace(object) { ... } # trace object's activities in the given block\ntrace_call { ... } # trace method calls in the given block\ntrace_exception { ... } # trace exceptions in the given block\n```\n\n### Tracer Classes\n\nIf you want to have more control over individual traces, you can use individual tracer classes:\n\n#### ObjectTracer\n\n```rb\nclass User\n  def initialize(name) = (@name = name)\n\n  def name() = @name\nend\n\ndef authorized?(user)\n  user.name == \"John\"\nend\n\nuser = User.new(\"John\")\ntracer = ObjectTracer.new(user)\ntracer.start do\n  user.name\n  authorized?(user)\nend\n\n #depth:3  #\u003cUser:0x000000010696cad8 @name=\"John\"\u003e receives #name (User#name) at test.rb:14:in `block in \u003cmain\u003e'\n #depth:3  #\u003cUser:0x000000010696cad8 @name=\"John\"\u003e is used as a parameter user of Object#authorized? at test.rb:15:in `block in \u003cmain\u003e'\n #depth:4  #\u003cUser:0x000000010696cad8 @name=\"John\"\u003e receives #name (User#name) at test.rb:8:in `authorized?'\n```\n\n#### IvarTracer\n\n\u003e [!Note]\n\u003e Ruby 3.0 and below's accessor calls don't trigger TracePoint properly so the result may be inaccurate with those versions.\n\n```rb\nrequire \"tracer\"\n\nclass Cat\n  attr_accessor :name\nend\n\ncat = Cat.new\n\ntracer = IvarTracer.new(cat, :@name)\ntracer.start do\n  cat.name = \"Kitty\"\n  cat.instance_variable_set(:@name, \"Ketty\")\nend\n\n#depth:3 Cat#name= sets @name = \"Kitty\" at test.rb:11\n#depth:3 Kernel#instance_variable_set sets @name = \"Ketty\" at test.rb:12\n```\n\n#### ExceptionTracer\n\n```rb\nExceptionTracer.new.start\n\nbegin\n  raise \"boom\"\nrescue StandardError\n  nil\nend\n\n#depth:0  #\u003cRuntimeError: boom\u003e raised at test.rb:4\n#depth:1  #\u003cRuntimeError: boom\u003e rescued at test.rb:6\n```\n\n#### CallTracer\n\n```rb\nclass User\n  def initialize(name) = (@name = name)\n\n  def name() = @name\nend\n\ndef authorized?(user)\n  user.name == \"John\"\nend\n\nuser = User.new(\"John\")\ntracer = CallTracer.new\ntracer.start do\n  user.name\n  authorized?(user)\nend\n\n #depth:4 \u003e    block at test.rb:13\n #depth:5 \u003e     User#name at test.rb:4\n #depth:5 \u003c     User#name #=\u003e \"John\" at test.rb:4\n #depth:5 \u003e     Object#authorized? at test.rb:7\n #depth:6 \u003e      User#name at test.rb:4\n #depth:6 \u003c      User#name #=\u003e \"John\" at test.rb:4\n #depth:6 \u003e      String#== at test.rb:8\n #depth:6 \u003c      String#== #=\u003e true at test.rb:8\n #depth:5 \u003c     Object#authorized? #=\u003e true at test.rb:9\n #depth:4 \u003c    block #=\u003e true at test.rb:16\n```\n\n#### LineTracer\n\n```rb\nclass User\n  def initialize(name) = (@name = name)\n\n  def name() = @name\nend\n\ndef authorized?(user)\n  user.name == \"John\"\nend\n\nuser = User.new(\"John\")\ntracer = LineTracer.new\ntracer.start do\n  user.name\n  authorized?(user)\nend\n\n #depth:4  at test.rb:14\n #depth:4  at test.rb:15\n #depth:5  at test.rb:8\n```\n\n### IRB-integration\n\nOnce required, `tracer` registers a few IRB commands to help you trace Ruby expressions:\n\n```\ntrace              Trace the target object (or self) in the given expression. Usage: `trace [target,] \u003cexpression\u003e`\ntrace_call         Trace method calls in the given expression. Usage: `trace_call \u003cexpression\u003e`\ntrace_exception    Trace exceptions in the given expression. Usage: `trace_exception \u003cexpression\u003e`\n```\n\n**Example**\n\n```rb\n# test.rb\nrequire \"tracer\"\n\nobj = Object.new\n\ndef obj.foo\n  100\nend\n\ndef bar(obj)\n  obj.foo\nend\n\nbinding.irb\n```\n\n```shell\nirb(main):001:0\u003e trace obj, bar(obj)\n #depth:23 #\u003cObject:0x0000000107a86648\u003e is used as a parameter obj of Object#bar at (eval):1:in `\u003cmain\u003e'\n #depth:24 #\u003cObject:0x0000000107a86648\u003e receives .foo at test.rb:10:in `bar'\n=\u003e 100\nirb(main):002:0\u003e trace_call bar(obj)\n #depth:23\u003e                            Object#bar at (eval):1:in `\u003cmain\u003e'\n #depth:24\u003e                             #\u003cObject:0x0000000107a86648\u003e.foo at test.rb:10:in `bar'\n #depth:24\u003c                             #\u003cObject:0x0000000107a86648\u003e.foo #=\u003e 100 at test.rb:10:in `bar'\n #depth:23\u003c                            Object#bar #=\u003e 100 at (eval):1:in `\u003cmain\u003e'\n=\u003e 100\n```\n\n## Customization\n\nTBD\n\n## Acknowledgements\n\nA big shout-out to [@ko1](https://github.com/ko1) (Koichi Sasada) for his awesome work on [`ruby/debug`](https://github.com/ruby/debug).\nThe [tracers in `ruby/debug`](https://github.com/ruby/debug/blob/master/lib/debug/tracer.rb) were an inspiration and laid the groundwork for this project.\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test-unit` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/ruby/tracer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/ruby/tracer/blob/master/CODE_OF_CONDUCT.md).\n\n## License\n\nThe gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).\n\n## Code of Conduct\n\nEveryone interacting in the Ruby::Tracer project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ruby/tracer/blob/master/CODE_OF_CONDUCT.md).\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruby%2Ftracer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruby%2Ftracer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruby%2Ftracer/lists"}