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

fix(console): don't make details requests with rewritten IDs #251

Merged
merged 1 commit into from
Jan 7, 2022

Conversation

hawkw
Copy link
Member

@hawkw hawkw commented Jan 6, 2022

PR #244 moved the rewriting of tracing span IDs to sequential
low-number IDs from the console-subscriber crate to the console CLI.
However, this introduced a bug with task details, because that PR didn't
change the part of the console that makes watch_details RPCs to use
the tracing span ID recieved from the remote --- it continued to use
the Task and Resource structs' id fields. These are now different
from the tracing ID recieved from the remote, because they're
rewritten in the console CLI. This means that watch_details RPCs would
generally recieve an error, or (in the off-chance that a rewritten ID
collides with a low-numbered tracing ID) the details for anoter task
or resource.

This branch fixes the bug by changing the Task and Resource structs
to store both the span ID received from the remote and the rewritten
pretty ID. This way, when we make watch_details RPC calls, we do it
with the span ID we received from the remote process.

I also changed some naming to make the distinction between rewritten IDs
and span IDs clearer.

PR #244 moved the rewriting of `tracing` span IDs to sequential
low-number IDs from the `console-subscriber` crate to the console CLI.
However, this introduced a bug with task details, because that PR didn't
change the part of the console that makes `watch_details` RPCs to use
the `tracing` span ID recieved from the remote --- it continued to use
the `Task` and `Resource` structs' `id` fields. These are now different
from the `tracing` ID recieved from the remote, because they're
rewritten in the console CLI. This means that `watch_details` RPCs would
generally recieve an error, or (in the off-chance that a rewritten ID
collides with a low-numbered `tracing` ID) the details for anoter task
or resource.

This branch fixes the bug by changing the `Task` and `Resource` structs
to store both the span ID received from the remote _and_ the rewritten
pretty ID. This way, when we make `watch_details` RPC calls, we do it
with the span ID we received from the remote process.

I also changed some naming to make the distinction between rewritten IDs
and span IDs clearer.
Copy link
Collaborator

@zaharidichev zaharidichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines +39 to +47
/// The resource's pretty (console-generated, sequential) ID.
///
/// This is NOT the `tracing::span::Id` for the resource's `tracing` span on the
/// remote.
num: u64,
/// The `tracing::span::Id` on the remote process for this resource's span.
///
/// This is used when requesting a resource details stream.
span_id: u64,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can rename it to just pretty_id or display_id?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm also fine with a name like that; i went with num because they're sequential numbers, but I'd be happy to change it.

Copy link
Collaborator

@zaharidichev zaharidichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hawkw
Copy link
Member Author

hawkw commented Jan 7, 2022

A follow-up that I didn't address in this branch, but that we probably ought to add, is something that's displayed in the UI when we can't get details for a task. Currently, when a watch_details RPC returns an error, we log it...but logs from the console aren't visible in the UI and can only be viewed if the user redirects them to a file. So, we probably want to add something in the UI showing that there was an error.

@hawkw hawkw merged commit 4ec26a8 into main Jan 7, 2022
@hawkw hawkw deleted the eliza/fix-details branch January 7, 2022 17:24
hawkw added a commit that referenced this pull request Jan 18, 2022
<a name=""></a>
##  (2022-01-18)

#### Features

*  feature-flag `tracing-journald` dependency (#250) ([24f25db](24f25db))
*  add vi style keybinds for tables (#223) ([1845c99](1845c99))

#### Bug Fixes

*  fix task lookup in async ops view (#257) ([9a50b63](9a50b63))
*  don't make details requests with rewritten IDs (#251) ([4ec26a8](4ec26a8))
*  fix build error with journald enabled ([a931b7e](a931b7e))
*  increase default event buffer capacity a bit (#235) ([0cf0aee](0cf0aee))
*  wrap controls line when the terminal is too narrow (#231) ([ef41507](ef41507))
*  don't enable crossterm mouse capture (#222) ([e020d66](e020d66), closes [#167](167))
hawkw added a commit that referenced this pull request Jan 18, 2022
<a name=""></a>
##  (2022-01-18)

#### Features

*  feature-flag `tracing-journald` dependency (#250) ([24f25db](24f25db))
*  add vi style keybinds for tables (#223) ([1845c99](1845c99))

#### Bug Fixes

*  fix task lookup in async ops view (#257) ([9a50b63](9a50b63))
*  don't make details requests with rewritten IDs (#251) ([4ec26a8](4ec26a8))
*  fix build error with journald enabled ([a931b7e](a931b7e))
*  increase default event buffer capacity a bit (#235) ([0cf0aee](0cf0aee))
*  wrap controls line when the terminal is too narrow (#231) ([ef41507](ef41507))
*  don't enable crossterm mouse capture (#222) ([e020d66](e020d66), closes [#167](167))
hawkw added a commit that referenced this pull request Jan 18, 2022
<a name=""></a>
##  (2022-01-18)

#### Features

*  feature-flag `tracing-journald` dependency (#250) ([24f25db](24f25db))
*  add vi style keybinds for tables (#223) ([1845c99](1845c99))

#### Bug Fixes

*  fix task lookup in async ops view (#257) ([9a50b63](9a50b63))
*  don't make details requests with rewritten IDs (#251) ([4ec26a8](4ec26a8))
*  fix build error with journald enabled ([a931b7e](a931b7e))
*  increase default event buffer capacity a bit (#235) ([0cf0aee](0cf0aee))
*  wrap controls line when the terminal is too narrow (#231) ([ef41507](ef41507))
*  don't enable crossterm mouse capture (#222) ([e020d66](e020d66), closes [#167](167))
hawkw added a commit that referenced this pull request Jan 18, 2022
<a name=""></a>
##  (2022-01-18)

#### Features

*  feature-flag `tracing-journald` dependency (#250) ([24f25db](24f25db))
*  add vi style keybinds for tables (#223) ([1845c99](1845c99))

#### Bug Fixes

*  fix task lookup in async ops view (#257) ([9a50b63](9a50b63))
*  don't make details requests with rewritten IDs (#251) ([4ec26a8](4ec26a8))
*  fix build error with journald enabled ([a931b7e](a931b7e))
*  increase default event buffer capacity a bit (#235) ([0cf0aee](0cf0aee))
*  wrap controls line when the terminal is too narrow (#231) ([ef41507](ef41507))
*  don't enable crossterm mouse capture (#222) ([e020d66](e020d66), closes [#167](167))
hawkw added a commit that referenced this pull request Jul 5, 2022
The console TUI's state model deals with two different types of IDs:

 - the actual `tracing` span IDs for an object (task, resource, or async
   op), which are *not* assigned sequentially, and may be reused over
   the program's lifetime, and
 - sequential "pretty" IDs assigned by the console, which are mapped to
   span IDs when an object is sent to the console. These are assigned
   based on separate counters for each type of object (so there can be
   both a task 1 and a resource 1, for example).

Remote span IDs are mapped to rewritten sequential IDs by the `Id` type,
which stores a map of span IDs to sequential IDs, and generates new
sequential IDs when a new span ID is recorded. The `Ids::id_for` method
takes a span ID and returns the corresponding sequential ID, and this
must be called before looking up or inserting an object by its remote
span ID.

Currently, *all* of these IDs are represented as `u64`s. This is
unfortunate, as it makes it very easy to accidentally introduce bugs
where the wrong kind of ID is used. For example, it's possible to
accidentally look up a task in the map of active tasks based on its span
ID on the remote application, which is likely to return `None` even if
there is a task with that span ID. PR #251 fixed one such ID-confusion
issue (where `WatchDetails` RPCs were performed with local, rewritten
task IDs rather than the remote's span ID for that task). However, it
would be better if we could just *not have* this class of issue.

This branch refactors the console's `state` module to make ID confusion
issues much harder to write. This is accomplished by adding an `Id`
newtype to represent our rewritten sequential IDs. `Ids::id_for` now
still takes a `u64` (as the remote span IDs are represented as `u64`s in
protobuf, so there's nothing we can do), but it returns an `Id` newtype.
Looking up or inserting objects in a state map now takes the `Id`
newtype. This ensures that all lookups are performed with sequential IDs
at the type level, and the only way to get a sequential ID is to ask the
`Ids` map for one.

Additionally, the `Id` type has a type parameter for the type of object
it identifies. This prevents additional issues where we might look up
the ID of a task in the map of resources, or similar.
hawkw added a commit that referenced this pull request Jul 5, 2022
The console TUI's state model deals with two different types of IDs:

 - the actual `tracing` span IDs for an object (task, resource, or async
   op), which are *not* assigned sequentially, and may be reused over
   the program's lifetime, and
 - sequential "pretty" IDs assigned by the console, which are mapped to
   span IDs when an object is sent to the console. These are assigned
   based on separate counters for each type of object (so there can be
   both a task 1 and a resource 1, for example).

Remote span IDs are mapped to rewritten sequential IDs by the `Id` type,
which stores a map of span IDs to sequential IDs, and generates new
sequential IDs when a new span ID is recorded. The `Ids::id_for` method
takes a span ID and returns the corresponding sequential ID, and this
must be called before looking up or inserting an object by its remote
span ID.

Currently, *all* of these IDs are represented as `u64`s. This is
unfortunate, as it makes it very easy to accidentally introduce bugs
where the wrong kind of ID is used. For example, it's possible to
accidentally look up a task in the map of active tasks based on its span
ID on the remote application, which is likely to return `None` even if
there is a task with that span ID. PR #251 fixed one such ID-confusion
issue (where `WatchDetails` RPCs were performed with local, rewritten
task IDs rather than the remote's span ID for that task). However, it
would be better if we could just *not have* this class of issue.

This branch refactors the console's `state` module to make ID confusion
issues much harder to write. This is accomplished by adding an `Id`
newtype to represent our rewritten sequential IDs. `Ids::id_for` now
still takes a `u64` (as the remote span IDs are represented as `u64`s in
protobuf, so there's nothing we can do), but it returns an `Id` newtype.
Looking up or inserting objects in a state map now takes the `Id`
newtype. This ensures that all lookups are performed with sequential IDs
at the type level, and the only way to get a sequential ID is to ask the
`Ids` map for one.

Additionally, the `Id` type has a type parameter for the type of object
it identifies. This prevents additional issues where we might look up
the ID of a task in the map of resources, or similar.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants