Debugging Rails Applications

 You must hear 'pry'?

From: /Users/twer/Projects/eportfolio/eportfolio/app/controllers/api/timeline_controller.rb @ line 6 Api::TimelineController#index:

     4: def index

     5:   found?(@user = User.find(params[:user_id])) do

 =>  6:     binding.pry

     7:     timeline_activities = @user.timeline_activities.order_by(:created_at.desc)

     8:     timeline_activities = timeline_activities.where(type: params[:category]) if params[:category].present?

     ......

[1] pry(#<Api::TimelineController>)> 

Sounds like inspecting variables?

Rails View Helpers

  • debug
  • to_yaml
  • inspect

debug

<%= debug @post %>

<p>

  <b>Title:</b>

  <%= @post.title %>

</p>

<pre>--- !ruby/object:Post

attributes:

  updated_at: 2008-09-05 22:55:47

  body: It's a very helpful guide for debugging your Rails app.

  title: Rails debugging guide

  published: t

  id: "1"

  created_at: 2008-09-05 22:55:47

attributes_cache: {}</pre>

 

Title: Rails debugging guide

to_yaml

<%= simple_format @post.to_yaml %>

<p>

  <b>Title:</b>

  <%= @post.title %>

</p>

--- !ruby/object:Post

attributes:

  updated_at: 2008-09-05 22:55:47

  body: It's a very helpful guide for debugging your Rails app.

  title: Rails debugging guide

  published: t

  id: "1"

  created_at: 2008-09-05 22:55:47

attributes_cache: {}

 

Title: Rails debugging guide

inspect

<%= [1, 2, 3, 4, 5].inspect %>

<p>

  <b>Title:</b>

  <%= @post.title %>

</p>

[1, 2, 3, 4, 5]

 

Title: Rails debugging guide

The Logger

What?

ActiveSupport::Logger/Log4r

How?

All logs are under Rails.root/log/, and named environment_name.log by default.

config/environment.rb

Rails.logger = Logger.new(STDOUT)

Rails.logger = Log4r::Logger.new("Application Log")

initializers

config.logger = Logger.new(STDOUT)

config.logger = Log4r::Logger.new("Application Log")

Log levels

Data in log files will not have level higher than configured log levels.

 

Use Rails.logger.level to view the current log level.

config.log_level = :warn # In any environment initializer, or

Rails.logger.level = 0 # at any time

:debug:info:warn:error:fatal, and :unknown

       0         1         2          3          4                     5

Logging

logger.(debug|info|warn|error|fatal)

logger.debug "Person hash: #{@person.attributes.inspect}"
logger.info "Processing the request..."
logger.fatal "Terminating application, raised unrecoverable error!!!"

:debug:info:warn:error:fatal, and :unknown

within a controller, model or mailer

Tagged Logging

logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))

logger.tagged("BCX") { logger.info "Stuff" }                            # Logs "[BCX] Stuff"

logger.tagged("BCX", "Jason") { logger.info "Stuff" }                   # Logs "[BCX] [Jason] Stuff"

logger.tagged("BCX") { logger.tagged("Jason") { logger.info "Stuff" } } # Logs "[BCX] [Jason] Stuff"

Impact of Logs on Performance

Bad performance if always using debug as logger level. (Disk I/O)

 

logger.debug "Person attributes hash: #{@person.attributes.inspect}"

 

logger.debug {"Person attributes hash: #{@person.attributes.inspect}"}

 

Still love pry?

try "debugger"

gem install debugger

and

use debugger on any line

restart server

rails server --debugger

dynamic require

under development env, require 'debugger'

 

Usage

(rdb:1) l

[4, 13] in /Users/twer/Projects/eportfolio/eportfolio/app/controllers/api/timeline_controller.rb

   8        debugger

=> 9        timeline_activities = @user.timeline_activities.order_by(:created_at.desc)

   10        timeline_activities = timeline_activities.where(type: params[:category])

(rdb:1) help

 

Available commands:

backtrace  delete   enable  help  list    ps       save    start   undisplay

break      disable  eval    info  method  putl     set     step    up       

catch      display  exit    irb   next    quit     show    thread  var      

condition  down     finish  jump  p       reload   skip    tmate   where    

continue   edit     frame   kill  pp      restart  source  trace 

Usage

list/l, l-, l=

backtrace/where, frame n, up n, down n

thread list, stop n, resume n, switch n

instance_variables

irb

v const, global, instance, local

display, undisplay

step/s, s+ n, s- n, next

break/b, b line, b file:line, b class(.|\#)method [if expression]

info breakpoints/break/b, delete n

enable, disable breakpoints

catch/cat exception-name

continue/c n, finish/fin [frame number]

 

 

Usage

edit file:line, tmate n

quit/q/exit

set reload, autolist, listsize n, forcestep, or save in ~/.rdebugrc

But it's dead after ruby 2.x

1.9: https://github.com/mark-moseley/ruby-debug

1.9.2/1.9.3: https://github.com/cldwalker/debugger

Use 'byebug' instead

ruby 2.x: https://github.com/deivid-rodriguez/byebug

Seems more powerful than pry?

https://github.com/pry/pry

Pry is not real debugger (REPL)

https://github.com/nixme/pry-debugger

https://github.com/deivid-rodriguez/pry-byebug

Enough?

Ruby is not perfect

Ruby Profiler

http://ruby-doc.org/stdlib-2.1.3/libdoc/profiler/rdoc/Profiler__.html

https://github.com/ruby-prof/ruby-prof

Usage

1. ruby-prof executable

2. ruby-prof API:

    result = RubyProf.profile do

    ...

    end

    printer = RubyProf::FlatPrinter.new(result)

    printer.print(STDOUT)

3. mode: 

    RubyProf.measure_mode = PROCESS_TIME, WALL_TIME, CPU_TIME, ALLOCATIONS, MEMORY, GC_RUNS, GC_TIME

or use

    export RUBY_PROF_MEASURE_MODE

    

Still want easier?

To be continued...

Made with Slides.com