Callback Tracing
View SourceThis is a complex feature which allows to see how functions in your LiveView application are being called.
Callback tracing is done inside Node Inspector
where you can see callbacks of selected node
or you can inspect all nodes inside Global Traces
Callback tracer can be in 2 states:
- Started - You see all traces live as you use your debugged application, you cannot use filters.
- Stopped - you need to refresh to see newest callbacks, you can use filters
By default it will be stopped when you change nodes or navigate to other LiveView.
How to use
Buttons
- Start - starts active tracing
- Refresh - loads newest traces
- Clear - removes traces (also the ones stored in memory)
Filters
Filters are used for both started tracing and refreshing. In Node Inspector
they can be accessed via button and are displayed in modal. You can reset each section or all of them. If you close modal without clicking Apply
nothing will change.
When using Global Traces
filters will be shown on the right (or in sidebar on small screens). To discard filters change you can click Revert changes button.
To better improve locating specific information you can filter by:
- Callbacks - When working in
Node Inspector
you will see eitherLiveView
orLiveComponent
callback names. InGlobal Traces
there will be all available callbacks to filter. It is useful when some you want to check specific part of your application (typicallyhandle_event
). - Execution Time - It is useful for checking bottlenecks in your app. You can set both minimal and maximal value (with unit).
Search and highlight
Search is a special filter available only for GLobal Traces
. It allows to query trace's arguments to filter traces and highlight searched phrase. It will highlight all occurrences inside callback arguments and expand structs to see all of them.
Trace information
Traces contain useful information:
- Callback name with arity
- Short preview of arguments (for easier differentiating)
- Timestamp of callback execution start
- Time of execution (yellow for slow and red for very slow)
Also in Global Traces
you have module name (when LiveComponent
then with CID
) which will redirect you to Node Inspector
with proper node selected.
When you expand a trace you will see detailed list of arguments.
You can copy each one of them if you want to process them in terminal.
You are also able to see them in fullscreen mode.
Traced callbacks
LiveDebugger traces callbacks of Phoenix.LiveView
and Phoenix.LiveComponent
behaviours in your application.
LiveView
handle_async/3
handle_call/3
handle_cast/2
handle_event/3
handle_info/2
handle_params/3
mount/3
render/1
terminate/2
LiveComponent
handle_async/3
handle_event/3
mount/1
render/1
update/2
update_many/1
Configuration
When you have complex application and Callback Tracing doesn't work after starting up then add delay of LiveDebugger setup:
config :live_debugger, :tracing_setup_delay, 200 # in ms
LiveDebugger is using garbage collection of traces in order to not take too much space in memory. Each debugged LiveView has separate table and default maximum size is 10MB. You can change it in config:
config :live_debugger, :approx_table_max_size, 20 # in MB
We are approximating size of elixir terms in garbage collection so the actual maximum value can be higher.
How Callback Tracing works
To properly check each callback we are leveraging erlang's :dbg
module. When the application starts :dbg.tracer/0
is initiated and calls for all LiveView or LiveComponent modules are added. It traces start of the callback, end of it and exceptions if some occur which allows to measure time of execution and which callback ended with error.
If you are using code reloading tracing may stop working due to modules being recompiled. To fix this issue see Settings
and either select automatic tracing refresh or do it manually.
Warning
Automatic tracing refresh may have negative impact on your app performance