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

Add display precision to log_diagnostics_plugin #6118

Closed
wants to merge 13 commits into from

Conversation

zeroacez
Copy link
Contributor

Objective

Fixes #6033

Solution

Added a variable num_of_decimals to the struct Diagnostic and modified log_diagnostics_plugin to use this variable as the display precision.

@zeroacez
Copy link
Contributor Author

I think I have done some sort of solution to the problem but I'm a little unsure of how the info! macro actually works and how the formatting works. I used $ but I don't really know why.
I took the approach to add a variable to Diagnostic. Doing this made me have to change some other places to use 6 as a temporary standard for the num_of_decimals. But at least now it's possible to set this variable when initializing the struct.

@alice-i-cecile alice-i-cecile added C-Usability A targeted quality-of-life change that makes Bevy easier to use A-Diagnostics Logging, crash handling, error reporting and performance analysis labels Sep 28, 2022
@zeroacez zeroacez marked this pull request as ready for review October 5, 2022 07:26
@@ -39,6 +39,7 @@ pub struct Diagnostic {
sum: f64,
max_history_length: usize,
pub is_enabled: bool,
pub num_of_decimals: usize, // Seams like it needs to be usize
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub num_of_decimals: usize, // Seams like it needs to be usize
pub num_of_decimals: usize, // Seems like it needs to be usize

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well that was a little bit embarrassing but it has been fixed now! ;)

@alice-i-cecile
Copy link
Member

Progress so far is great, but I'd like to see about making this user configurable before merging it.

@zeroacez
Copy link
Contributor Author

zeroacez commented Nov 3, 2022

Thank you!
Sounds good. Did you have a specific way you wanted to go about making it user configurable?

@@ -48,6 +48,7 @@ impl<T: Asset> AssetCountDiagnosticsPlugin<T> {
}
),
20,
6, // TODO: let user pick num_of_decimals
Copy link
Member

Choose a reason for hiding this comment

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

This should be hard set to 0: you can't load a fractional asset.

@@ -19,7 +19,8 @@ impl EntityCountDiagnosticsPlugin {
DiagnosticId::from_u128(187513512115068938494459732780662867798);

pub fn setup_system(mut diagnostics: ResMut<Diagnostics>) {
diagnostics.add(Diagnostic::new(Self::ENTITY_COUNT, "entity_count", 20));
diagnostics.add(Diagnostic::new(Self::ENTITY_COUNT, "entity_count", 20, 6));
Copy link
Member

Choose a reason for hiding this comment

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

Same here: fractional entities aren't a thing.

@alice-i-cecile
Copy link
Member

Let me take a look in earnest! So, we can already configure this when building them manually, which is great. But for the plugins, it looks like there's two kinds in play:

  1. Plugins that count something discrete, and should never display any decimal points (these need another refactor after this to just store and report a u64).
  2. Plugins that should be configurable, as they report a floating point value.

For 2, I'd recommend the new pattern introduced in #6360 :)

@zeroacez
Copy link
Contributor Author

zeroacez commented Nov 22, 2022

Hey! I'm back looking at this and I don't think I really understand what you want me to do. Are you suggesting that I update the log_diagnostics_plugin to use this new standard or that i change something in diagnostic to take the num_of_decimals as an argument? Or do you have something entirely different in mind?

Sorry I've been busy lately but now I'm ready and hoping to get this done ASAP.

@alice-i-cecile alice-i-cecile added the M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide label Nov 22, 2022
@alice-i-cecile
Copy link
Member

Good questions, sorry for being unclear.

Diagnostic::num_of_decimals should store an enum. One arm should be used for integer values, the other for decimal values.

update the log_diagnostics_plugin to use this new standard

Yes: I think we can use this pattern to solve // TODO: let user pick num_of_decimals :)

@zeroacez
Copy link
Contributor Author

Ok I got some help to understand what you wanted, still a little bit unsure if this is what you were thinking about, and we came up with this solution. So now it's an enum and there is a get_num_of_decimals function that returns the value and is used in log_diagnostic in log_diagnostic_plugin.

Also we put some trait code in comments that we tried to use so we don't have to do any new imports but it didn't work. Could it be done using this? Or is there maybe an other way?

@@ -41,7 +65,7 @@ pub struct Diagnostic {
ema_smoothing_factor: f64,
max_history_length: usize,
pub is_enabled: bool,
pub num_of_decimals: usize, // Seems like it needs to be usize
pub num_of_decimals: DisplayPercision, // Seems like it needs to be usize
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub num_of_decimals: DisplayPercision, // Seems like it needs to be usize
pub num_of_decimals: DisplayPercision,

@@ -28,6 +28,30 @@ pub struct DiagnosticMeasurement {
pub value: f64,
}

/// Enum for display percision. Choose IntergerValue for discrete values and DecimalValue(num_of_decimals) to specify the number of decimals
#[derive(Debug)]
pub enum DisplayPercision {
Copy link
Member

Choose a reason for hiding this comment

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

Precision, not percision :) In the docs too.

@@ -28,6 +28,30 @@ pub struct DiagnosticMeasurement {
pub value: f64,
}

/// Enum for display percision. Choose `IntegerValue` for discrete values and `DecimalValue(num_of_decimals)` to specify the number of decimals
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Enum for display percision. Choose `IntegerValue` for discrete values and `DecimalValue(num_of_decimals)` to specify the number of decimals
/// The number of digits that should be displayed for a diagnostic.
///
/// Choose `IntegerValue` for discrete values and `DecimalValue(num_of_decimals)` to specify the number of decimals.

}

impl DisplayPercision {
pub fn get_num_of_decimals(&self) -> usize {
Copy link
Member

Choose a reason for hiding this comment

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

I think num_decimals is a perfectly clear and shorter name here :)

@alice-i-cecile
Copy link
Member

Good progress! This is the right direction for sure.

Also we put some trait code in comments that we tried to use so we don't have to do any new imports but it didn't work. Could it be done using this? Or is there maybe an other way?

Unsure; let me ask for some additional eyes to help get you unstuck :)

@@ -41,6 +65,7 @@ pub struct Diagnostic {
ema_smoothing_factor: f64,
max_history_length: usize,
pub is_enabled: bool,
pub num_of_decimals: DisplayPercision, // Seems like it needs to be usize
Copy link
Member

Choose a reason for hiding this comment

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

I think the name num_of_decimals is clunky and does not clarify its intent. I prefer the name precision as mentioned in the original issue.

pub enum DisplayPercision {
IntegerValue,
DecimalValue(usize),
}
Copy link
Member

Choose a reason for hiding this comment

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

Why have an enum for this?

Running the code in the rust playground:

fn main() {
    let x = 5.678912345;
    dbg!(format!("{x:.6}"));
    dbg!(format!("{x:.0}"));
}

This prints:

[src/main.rs:3] format!("{x:.6}") = "5.678912"
[src/main.rs:4] format!("{x:.0}") = "6"

I don't think an enum is necessary? You can just use 0 to print an integer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just added the enum. Just using a usize is how I did it to begin with.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm. @alice-i-cecile I have a hard time understanding why turning this into an enum is better. Can you clarify why?

Copy link
Member

Choose a reason for hiding this comment

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

Certain diagnostics will always be integer-valued: users should not be able to configure the number of decimals for them. Other diagnostics are float-like, and users may want to round to the nearest whole number.

To me, these cases are distinct (even though the same number of decimal places are shown). Representing that in the type system means that we'll be able to expose the correct controls to users later.

Copy link
Member

Choose a reason for hiding this comment

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

Do IntegerValue and DecimalValue(0) have different behavior?

Copy link
Member

Choose a reason for hiding this comment

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

Not in the current version of this PR. I'll play with this by next Monday, and try to get a full design here as a PR to @zeroacez branch :)

Comment on lines 40 to 43
match self {
DisplayPercision::IntegerValue => 0,
DisplayPercision::DecimalValue(x) => *x,
}
Copy link
Member

Choose a reason for hiding this comment

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

This indicates that making an enum is redundant, as you can just use usize directly here.

Comment on lines +47 to +54
// trait DiagnosticDisplayPercision {
// type DisplayPercision;
// }

// impl DiagnosticDisplayPercision for Diagnostic {
// type DisplayPercision = DisplayPercision;
// }

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// trait DiagnosticDisplayPercision {
// type DisplayPercision;
// }
// impl DiagnosticDisplayPercision for Diagnostic {
// type DisplayPercision = DisplayPercision;
// }

@@ -73,11 +98,12 @@ impl Diagnostic {
.push_back(DiagnosticMeasurement { time, value });
}

/// Create a new diagnostic with the given ID, name and maximum history.
/// Create a new diagnostic with the given ID, name, maximum history and number of decimals.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Create a new diagnostic with the given ID, name, maximum history and number of decimals.
/// Create a new diagnostic with the given ID, name, maximum history and decimal precision.

pub fn new(
id: DiagnosticId,
name: impl Into<Cow<'static, str>>,
max_history_length: usize,
num_of_decimals: DisplayPercision, // Choose number of decimals for display precision.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
num_of_decimals: DisplayPercision, // Choose number of decimals for display precision.
num_of_decimals: DisplayPercision,


// trait DiagnosticDisplayPercision {
// type DisplayPercision;
// }
Copy link
Member

Choose a reason for hiding this comment

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

Please do not leave intentionally commented out code in the codebase. If it's not meant to be included, please remove it. Otherwise, please complete the implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I left it in in regards to this:

Also we put some trait code in comments that we tried to use so we don't have to do any new imports but it didn't work. Could it be done using this? Or is there maybe an other way?

But if there is no answer I'll remove it :)

@richchurcher
Copy link
Contributor

Backlog cleanup: closing due to inactivity, existing issue #6033 remains.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Diagnostics Logging, crash handling, error reporting and performance analysis C-Usability A targeted quality-of-life change that makes Bevy easier to use M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add display precision to diagnostics
5 participants