-
Notifications
You must be signed in to change notification settings - Fork 189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filtered process list #411
base: main
Are you sure you want to change the base?
Conversation
Hi @bokner! Thanks for the PR. I think we should simplify this a bit. I think we could have a So the goal is to only filter processes but not customize rendering. WDYT? |
Hi @josevalim, I also realized that more work needs to be done to sync up my code with the latest changes. I started out forking v0.7.1, and I see that things changed quite a bit. |
I see. So in this case, I don't think it is a filter, is it? You want to argument the information. Perhaps we should have a ProcessInfo behaviour but it has to return a keyword list of data, instead of rendering on its own. |
But it is a filter :-) Perhaps, the example of implementation would explain the intention better(sorry, I should have thought about it!): defmodule ProcessFilter.Demo do
@behaviour Phoenix.LiveDashboard.ProcessFilter
def list() do
["Registered", "All"]
end
def filter("Registered") do
Process.registered() |> Enum.map(fn name -> %{pid: Process.whereis(name), name_or_initial_call: name, extra: "extra_param"} end)
end
def filter("All") do
Process.list()
end
def render_process_info(assigns, filter) when filter in ["Registered"] do
render(Map.put(assigns, :filter, filter))
end
def render_process_info(_assigns, _filter) do
nil
end
use Phoenix.LiveDashboard.Web, :live_component
def render(assigns) do
~H"""
<div class="tabular-info">
<%= if @alive do %>
<table class="table table-hover tabular-info-table">
<tbody>
<tr><td class="border-top-0">Filtered by</td><td class="border-top-0"><pre><%= @filter %></pre></td></tr>
<tr><td class="border-top-0">Registered name</td><td class="border-top-0"><pre><%= @registered_name %></pre></td></tr>
<tr><td>Total heap size</td><td><pre><%= @total_heap_size %></pre></td></tr>
<tr><td>Heap size</td><td><pre><%= @heap_size %></pre></td></tr>
<tr><td>Stack size</td><td><pre><%= @stack_size %></pre></td></tr>
<tr><td>Reductions</td><td><pre><%= @reductions %></pre></td></tr>
<tr><td>Current stacktrace</td><td><pre><%= @current_stacktrace %></pre></td></tr>
</tbody>
</table>
<%= if @page.allow_destructive_actions do %>
<div class="modal-footer">
<button class="btn btn-danger" phx-target={@myself} phx-click="kill">Kill process</button>
</div>
<% end %>
<% else %>
<div class="tabular-info-not-exists mt-1 mb-3">Process is not alive or does not exist.</div>
<% end %>
</div>
"""
end
end So here we have two options for filtering process list, and the process info view for registered processes is customized. |
Got it. So I think it is good but instead of render_process_info we should call it extra_process_info and return a keyword list, WDYT? |
I like the idea of not dealing with rendering outside of the ProcessInfoComponent, but I'm not sure how do we customize the rendering then? For instance, for some processes, we want to remove registered name and/or some other things, add application-specific links (not just the table rows) etc. Perhaps, we could just provide a list of elements for |
So perhaps we may need to return structured data, such as map with key, value and an optional link. |
Actually, let’s call it extra_info only, without process, because we can use the same behavior to extend other pages later. :) |
d5021bd
to
a13b1a9
Compare
…iveView.Rendered, list or nil
I think, in addition to returning the content as structured data for the component to render it, we might also want to provide a way to render the content info page directly by the implementation module. The reasoning is that the markup for the info page could be quite complex (as it is for our particular use case), i.e., not limited by the table, basic links, etc. Then the corresponding callback would be @callback info_content(assigns :: Socket.assigns(), filter_name :: String.t() | nil) ::
Phoenix.LiveView.Rendered.t() | [map()] | nil An example of an implementation that returns the list of maps: def info_content(assigns, filter) do
info_list(assigns)
end
defp info_list(assigns) do
[
%{label: "Registered name", value: assigns.registered_name},
%{label: "Total heap size", value: assigns.total_heap_size},
## some other pieces
]
end An example of an implementation that returns the template: def info_content(assigns, filter) do
info_template(assigns)
end
defp info_template(assigns) do
~H"""
<table class="table table-hover tabular-info-table">
<tbody>
<tr><td class="border-top-0">Registered name</td><td class="border-top-0"><pre><%= @registered_name %></pre></td></tr>
<tr><td>Total heap size</td><td><pre><%= @total_heap_size %></pre></td></tr>
</tbody>
</table>
"""
end Both variations are currently handled by |
Unfortunately for us that is a no-go because we don't want people to assume it is being rendered in a certain way or in a certain part. We need to keep everything driven by Elixir data. |
Do you have a screenshot of what you want to render right now? And which kind of rich data would be necessary to achieve it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, it has a lot of potentials, but am unsure how to implement it correctly. I know this PR is WIP, but I left some comments just in case.
About the idea, I think #409 would be a better abstraction for dealing with the custom modal problem. We can detect if it is a "special" process and render a different modal, if not, we can delegate to the regular one.
I'm not 100% sure if I like the filter idea. We already have a good abstraction for this: row_fetcher
. Instead of modifying the current behaviour to add more complexity, we could change the row_fetcher
"in runtime using a select input" to a custom one. We could expose current helpers for remote execution, order, limit, and filter to simplify this process.
However, all my suggestions would increase the public API making the project harder to maintain in the long term.
Finally, you can always create your own custom page using this PR as a reference.
Co-authored-by: Alex Castaño <[email protected]>
Co-authored-by: Alex Castaño <[email protected]>
Co-authored-by: Alex Castaño <[email protected]>
Co-authored-by: Alex Castaño <[email protected]>
Thank you for the feedback @alexcastano. I'm not sure I completely understand your idea. We would have to introduce some customization either way. Currently, the modification in the original code is limited by the addition of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello again! I've just added some comments to clarify what changes I see as essential before merging :)
In the code, |
I would argue that if the implementation has "XXX" in the filter list, it probably does not make sense not to have |
Sorry, but I don't get it. I don't see any Maybe are you confused because |
I don't think it is a problem to have always the "All" option. AFAIK the |
It is a problem for us, and that's also the reason why we avoid using observer :-) Edit:
The issue is not so much with how many rows are shown, but rather with server-side polling a potentially huge number of processes and retrieving process info for each of them. |
You are right, there is none :-)
So the Otherwise, the Please let me know if you see any problems with this description or the way to improve the code. |
Okay, maybe you could help me to fix it. This line is here because I wasn't able to make the condition in the form
to work without assigning |
Fair enough. If you find this problem it makes sense to avoid it.
Yeah, this is true, but we can use any name in fact.
This is not true. We are only changing the Later, when we call fetch_rows it returns the 5-element tuple, it will return We use We cannot do exactly the same for We should update We should show the filter input only if I think this way we fix all the issues related to this. I hope I explained better this time :) |
Great, that makes sense, thank you @alexcastano for the explanation and patience :-) |
45e5abf
to
e056334
Compare
80499ee
to
408a28b
Compare
Co-authored-by: Alex Castaño <[email protected]>
…e_dashboard into filtered_process_list * 'filtered_process_list' of github.com:bokner/phoenix_live_dashboard: Simplify the base implementation of default_filter/0
@alexcastano @josevalim I think I covered most of your suggestions. I also ran some manual tests, and it looks functional. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work! It looks good to me :)
Allow custom implementation of process lists. The motivation is to be able to inspect specific groups of processes rather than pulling the whole process list. For instance, we may want to look at the processes from the specific registry, supervised by a specific supervisor, etc.