-
Notifications
You must be signed in to change notification settings - Fork 7
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 more logging to mark-scan #4569
Conversation
await logger.log( | ||
LogEventId.PollWorkerConfirmedBallotRemoval, | ||
'poll_worker' | ||
); |
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.
Most behavior requiring logs is common to VxMark or covered in the backend
bcbd640
to
3831e82
Compare
While these events are technically covered by automatic state transition logging, explicitly logging these is cheap and makes compliance clear
442fc43
to
ad771f1
Compare
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.
Needs CircleCI config updates.
@@ -29,6 +32,7 @@ function renderWithAuthAndBallotContext( | |||
): VxRenderResult { | |||
return render( | |||
<BallotInvalidatedPage | |||
logger={logger} |
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.
Feels like we need a useLogger
hook.
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.
In line with discussion in #4592 (comment), 579f510 moves logging to the backend
Clean up unnecessary multiline calls to `log!` and use shorthand where possible Co-authored-by: Brian Donovan <[email protected]>
Don't crash on pin read errors and simplify pin value comparison Co-authored-by: Brian Donovan <[email protected]>
Co-authored-by: Brian Donovan <[email protected]>
2a314ae
to
43ef878
Compare
); | ||
Ok(size) => match handle_command(&serial_buf[..size]) { | ||
Ok(key_option) => { | ||
if key_option.is_some() { |
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.
Refactored handle_command
to avoid passing the device
, which is cumbersome to create in CI because it requires special permissions. This seemed easier than configuring udev rules for CI.
The downside is I introduced this nested conditioning to handle when the command should no-op ie. when the controller indicates one of its buttons was released. We only want to send keyboard events when the button is depressed.
To support this, handle_command
returns Some(keyboard::Key)
on controller button press, and None(keyboard::Key)
on button release.
Open to feedback on how to handle these checks more cleanly/inline.
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.
This can be improved by being more specific about the types you're looking for in your match arms:
Ok(Some(key)) => {
if let Err(err) = send_key(&mut device, key) {
log!(EventId::UnknownError, "Error sending key: {err}");
}
}
Ok(None) => {}
In general, you don't want to use is_some()
or is_ok()
et al when you want the value being wrapped. Use match
/if let
/let/else
destructuring
// In prod we wait 1s for the device to register. | ||
// We can afford to be riskier to speed up tests. | ||
thread::sleep(DEVICE_WAIT_DURATION); |
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.
This isn't needed, right?
let key_option = handle_command(&data).unwrap(); | ||
assert!(key_option.is_some()); | ||
assert_eq!(key_option.unwrap(), keyboard::Key::R); |
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 recommend this:
let key_option = handle_command(&data).unwrap(); | |
assert!(key_option.is_some()); | |
assert_eq!(key_option.unwrap(), keyboard::Key::R); | |
assert_eq!(handle_command(&data).unwrap().unwrap(), keyboard::Key::R); |
In tests, unwrapping Option
and Result
generally provides more useful error messages than assert!(key_option.is_some())
or assert!(result.is_ok())
. For example:
called `Result::unwrap()` on an `Err` value: UnexpectedDataLength(258)
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.
Rebase weirdness?
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.
Somewhere along the way this code path was reported as uncovered so I added this test.
ad796d2
to
74cb5de
Compare
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.
A couple minor things, but LGTM!
set_up_pins().unwrap_or_else(|error| { | ||
log!( | ||
event_id: EventId::ConnectToPatInputComplete, | ||
disposition: Disposition::Failure, | ||
message: format!("An error occurred during GPIO pin connection: {error}") | ||
); | ||
}); |
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.
When you're not using the value it seems a little weird to use unwrap_or_else
. Maybe do this?
set_up_pins().unwrap_or_else(|error| { | |
log!( | |
event_id: EventId::ConnectToPatInputComplete, | |
disposition: Disposition::Failure, | |
message: format!("An error occurred during GPIO pin connection: {error}") | |
); | |
}); | |
if let Err(error) = set_up_pins() { | |
log!( | |
event_id: EventId::ConnectToPatInputComplete, | |
disposition: Disposition::Failure, | |
message: format!("An error occurred during GPIO pin connection: {error}") | |
); | |
} |
Also, do we want to continue after this?
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.
5171668
good catch, thank you
@@ -0,0 +1,138 @@ | |||
use pin::Pin; |
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.
Write a //!
module-level doc comment? I know a fair amount of the existing Rust code doesn't do this, but I'm trying to encourage better habits here.
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.
doc comments added to both daemons and Pin
struct
/// Makes the pin accessible from userspace. If the pin is already set up due to | ||
/// a previous `set_up` call, or from other callers of the sysfs interface, `set_up` | ||
/// will tear down the pin and attempt one more time to set up. This may cause | ||
/// interruption to other processes attempting to read the pin value. |
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.
This brings up the question of whether we should just continue when we see the pin is already exported. IMO since we expect this daemon to be the only exporter it should never rely on the unexpected state of the pin already being exported. ie. it should always be exercising the path to export the pin.
@@ -51,6 +72,9 @@ impl Pin { | |||
self.set_direction_in() | |||
} | |||
|
|||
/// Reads the pin value and returns the boolean inverse of the pin's raw value. | |||
/// # Example | |||
/// When the pin's value is b'0', `is_active` returns true. |
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 believe this convention is specific to VSAP's implementation, so it could arguably live in the daemon code. But since we have no planned use for this module outside the PAT integration it feels cleaner to leave this translation in the pin module.
Overview
#3983
Demo Video or Screenshot
N/A
Testing Plan
Checklist