Skip to content
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

Display value of '$process_label' in observer #5039

Closed
wants to merge 1 commit into from

Conversation

rlipscombe
Copy link
Contributor

In http://erlang.org/pipermail/erlang-questions/2021-May/100972.html, it was suggested (after some discussion) that non-unique process labels would make using observer nicer. I followed this up here: http://erlang.org/pipermail/erlang-questions/2021-June/101152.html

This is a first stab at implementing that, for feedback.

It defines a convention where the process dictionary can contain '$process_label', which is assumed to be an Erlang string (list of chars). If there's interest in the concept, I'll look at extending gen_server et. al. to support this through options.

I'm currently using it to make it easier to observe a particularly nested supervision tree.

@CLAassistant
Copy link

CLAassistant commented Jul 9, 2021

CLA assistant check
All committers have signed the CLA.

@KennethL KennethL added the team:PS Assigned to OTP team PS label Jul 12, 2021
@michalmuskala
Copy link
Contributor

Would it make sense to support any term in there and use io_lib:format("~p") on it? I could imagine something like {service_x, 1} for some sort of sharded service. A tuple like that would still be very readable in observer output

@galdor
Copy link

galdor commented Jul 12, 2021

I would expect this kind of property to at least support strings, binaries and tuples: as Michał said, there are multiple reasons to use a multi-valued label, e.g. {acceptor, <name>}, {db_client, <id>}…).

Note that for tuples, ~tp should always be used: Erlang does not support non-latin1 characters by default, even if your system uses a UTF-8 locale (and I have no hope for this to ever change).

@rlipscombe rlipscombe force-pushed the rl/observer-labels branch 2 times, most recently from 2111552 to f0e6f38 Compare July 13, 2021 16:09
@rlipscombe
Copy link
Contributor Author

rlipscombe commented Jul 13, 2021

I've updated the commit to allow process labels to be any term.

@galdor
Copy link

galdor commented Jul 13, 2021

You need to separate formatting of strings (lists or binaries) and other terms; using ~p for strings will return quoted values (e.g. "foo" and <<"foo">>).

Something such as:

case proplists:get_value('$process_label', D) of
    undefined ->
        pid_to_list(P);
    Label when is_list(Label); is_binary(Label) ->
        io_lib:format("~ts ~tp", [Label, P]);
    Label ->
        io_lib:format("~tp ~tp", [Label, P])
end;

@dgud
Copy link
Contributor

dgud commented Oct 1, 2021

So we agreed that this is useful information but it was decided that we should have
an api for setting and getting this information, so that where (and how) the data is
stored can be changed.

'proc_lib' or 'sys' might be a good place for this functionality with set/get_process_description/1.

@rlipscombe
Copy link
Contributor Author

'proc_lib' or 'sys' might be a good place for this functionality with set/get_process_description/1.

Is there a compelling reason to choose one over the other? Based on a quick skim through the docs, it seems to me that 'sys' would be the better place, since it's already got "inspection"-type stuff in it.

@dgud
Copy link
Contributor

dgud commented Oct 1, 2021

We have not discussed the name or where to put them it was just a suggestion, we leave that to you
for now and will take that discussion when a new (or updated) PR arrives :-)

@IngelaAndin IngelaAndin added the waiting waiting for changes/input from author label Oct 5, 2021
@rlipscombe
Copy link
Contributor Author

Just to be clear: I've not forgotten about this; been busy with the day job.

@rlipscombe rlipscombe force-pushed the rl/observer-labels branch 2 times, most recently from 8d040bd to 8a8d142 Compare November 22, 2021 21:20
@rlipscombe
Copy link
Contributor Author

I've updated the PR. See the new commit.

@dgud dgud removed the waiting waiting for changes/input from author label Jan 5, 2022
@IngelaAndin IngelaAndin added the stalled waiting for input by the Erlang/OTP team label Feb 9, 2022
@nathanl
Copy link
Contributor

nathanl commented Mar 25, 2022

Still wishing and hoping for this to land. ✨ ✨ ✨

@rlipscombe
Copy link
Contributor Author

I've got time to work on this now, but I'm waiting for some feedback on the implementation.

@dgud
Copy link
Contributor

dgud commented Mar 25, 2022

Yes, I have been thinking on this on and off, and don't know what to do about it.

What I want to avoid is a performance load on the target node, and as it is today getting the
process_dictionary on another process can be expansive (if large).

Now as it is written in the current PR, it is used in observer in the application tab only,
which is almost never updated and only fetched for the displayed application processes
and that should be ok.

But if we add it there people will want it in the 'Processes' tab, at least I want it there, (which works as 'top') and then it will be fetched on every update (1-10s) and for all processes.
We already fetch the '$initial_call' there which will do a second copy of the dictionary.

@rlipscombe
Copy link
Contributor Author

If we discard the idea of sys:get_label, etc., and lean into using the process dictionary, can we make only one copy of the dictionary?

I prefer using a well-known value in the process dictionary because it removes short-term compatibility concerns: I can decorate my code with labels without worrying about which version of OTP I'm targetting. It adds coupling in the long term, though.

@dgud
Copy link
Contributor

dgud commented Mar 30, 2022

We decided to use a functional interface so we can change it later to something with more performance.

But maybe move the functions to proc_lib and add a new function there,
that lookup the label and if it does not exist lookup the initial call.

@IngelaAndin IngelaAndin removed the stalled waiting for input by the Erlang/OTP team label Mar 30, 2022
@IngelaAndin IngelaAndin added the waiting waiting for changes/input from author label Apr 27, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Jun 7, 2022

CT Test Results

       3 files       96 suites   38m 40s ⏱️
1 894 tests 1 832 ✔️ 62 💤 0
2 190 runs  2 126 ✔️ 64 💤 0

Results for commit f876043.

♻️ This comment has been updated with latest results.

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

@rlipscombe
Copy link
Contributor Author

rlipscombe commented Jun 8, 2022

But maybe move the functions to proc_lib.

Can do, but...

add a new function there, that lookup the label and if it does not exist lookup the initial call

I don't like this. The fallback from the label to the initial call feels like an observer concern, and it feels like we'd be polluting proc_lib with it.

as it is today getting the process_dictionary on another process can be expansive (if large).

This feels like it needs further discussion. If we provided a way to get only some of the process dictionary, and if we continued to keep the process label in the dictionary, something like erlang:get_process_dictionary(Pid, Keys) would address that concern. I know you've talked about a functional API, but proc_lib keeps a bunch of other things in the dictionary, so keeping the label in there doesn't seem like much of a departure.

observer could use it like this:

Term = case erlang:get_process_dictionary(Pid, ['$process_label', '$initial_call']) of
    [L, _] when L =/= undefined -> L;
    [_, IC] when IC =/= undefined -> IC;
    _ -> undefined
end

However: is there any evidence that large process dictionaries are common, and how much impact does it really have...?

@IngelaAndin IngelaAndin added the stalled waiting for input by the Erlang/OTP team label Oct 5, 2022
@paulo-ferraz-oliveira
Copy link
Contributor

Today I ran into an issue that would benefit from this (process label on Observer). Is this pull request still being considered? I see it as marked Stalled, but don't know why.

@dgud
Copy link
Contributor

dgud commented Dec 13, 2022

Not in the current form, but stalled means we need to take a look at this but it is down on the priority list.

@rlipscombe
Copy link
Contributor Author

Stalled, but don't know why.

That's on me. I stepped away from working with Erlang for a few months. Nudging discussion slightly:

I don't like this. The fallback from the label to the initial call feels like an observer concern, and it feels like we'd be polluting proc_lib with it.

I've thought about this some more, and I'm thinking that proc_lib could use the initial call as a default for the label, if it's not specified. That's neater.

So it'd look something like this:

  1. The various spawn functions in proc_lib could take an optional label parameter. If not specified, it would use the initial call as the label.
  2. For now (implementation detail) the label goes in the process dictionary.
  3. proc_lib provides functions to get/set the label.
  4. observer uses the function to get the label.

It's relatively low-impact, hides the implementation details, and is easy to change later.

We add the concept of non-unique labels for processes, which are
displayed in observer.

A process can have at most one label; labels need not be unique between
processes. Labels can be any valid Erlang term.

This adds `sys:put_label/1`, `sys:get_label/0` and `sys:get_label/1`
function.

See http://erlang.org/pipermail/erlang-questions/2021-May/100972.html
and http://erlang.org/pipermail/erlang-questions/2021-June/101152.html
for discussion.

The labels are currently stored in the process dictionary (under
'$process_label'), but this is an implementation detail.
@rlipscombe
Copy link
Contributor Author

I've looked into a couple of options:

  1. Putting this in proc_lib:spawn_opt -- that's brittle, 'cos init_p is exported as-is, relied on by a few other things, and I have no way of knowing if other code relies on it.
  2. Addressing the dictionary performance thing, I think erlang:process_dictionary(Pid) and erlang:process_dictionary(Pid, KeyOrKeys) would be really useful. But I looked at the BIF code for process_info/2 and I do not want to go anywhere near that stuff without a run-up.

So: I think the least-bad option at this point is:

  1. to go with sys:put_label/1 and sys:get_label/0,1. For now, those can use the process dictionary (but as an implementation detail, not to be relied on). If someone is brave enough to add erlang:process_dictionary/1,2 all well and good.
  2. Observer to not fall back to $initial_call because of the performance concern (but I could be talked round).
  3. Follow-up PRs to get gen_foo.erl to take a label option and call sys:put_label.

This is basically the state of the PR right now. If that's not good enough, then I'm out of ideas.

@nathanl
Copy link
Contributor

nathanl commented Jan 23, 2023

Although "observer" is in the issue title, I like that this code is not Observer-specific. These labels could be useful in Observer itself and also other tools like it, such as Phoenix.LiveDashboard's process view

@dgud
Copy link
Contributor

dgud commented Oct 9, 2023

Replaced by #7720

@dgud dgud closed this Oct 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stalled waiting for input by the Erlang/OTP team team:PS Assigned to OTP team PS waiting waiting for changes/input from author
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants