-
Notifications
You must be signed in to change notification settings - Fork 1
feat: summary metric #47
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
Conversation
deps: metrics-util for Summary logic feat: GenericSummary, converts into prometheus proto's Summary feat: SummaryVecBuilder enabling SummaryVec feat: SummaryVec, mirrors HistogramVec
fix: clippy lints
refactor(derive): `buckets`/`quantiles` attributes and invariant checks
feat(example): add Summary usage
fix(examples): add missing help strings
feat(summary): rolling summary
feat(summary): ConcurrentSummaryProvider docs: improve documentation chore: cleanup `core` dead file deps: feature-gate summary deps
chore: cleanup unused MetricType::Summary.1 field test: ensure quantile defaults work chore: remove unused `GenericSummary::observe` refactor: rename `GenericSummary::concurrent_observe` to `observe`
mempirate
left a comment
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.
First pass, primarily some style stuff. Very nice job
| &self, | ||
| maybe_buckets: Option<syn::Expr>, | ||
| maybe_quantiles: Option<syn::Expr>, | ||
| ) -> Result<Partitions> { |
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 could return Result<Option<Partitions>> and we can remove the Partitions::{None, NotApplicable} variants. Up to you
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 thought about it, but decided to go with more explicit variants, to preserve the semantics better, if one day we need to change this I'd rather have it much clearer
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.
Can you elaborate more on how you preserve the semantics better?
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.
To indicate that this parsed item is specifically for this usecase, but also if we want to make hard errors out of "NotApplicable" we could, for example if it was provided and we were processing a Counter
I can rework it to be an option, in the end it's a small difference, it's just that when parsing I prefer to be explicit about the various options, especially since we have an enum already (for buckets/quantiles, which ok could be just the inner syn::Expr)
|
Changed to |
test(arccell): check invariants are upheld
refactor: new batch reserves
merklefruit
left a comment
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.
Awesome work! Leaving some questions to understand for myself 🙂
Co-authored-by: nicolas <48695862+merklefruit@users.noreply.github.com>
fix: deadlock with cloned GenericSummary (not a full clone) fix(summary:generic): usage with MetricVecBuilder test: summary + macro smoke test refactor: SummaryProvider -> NonConcurrentSummaryProvider refactor: ConcurrentSummaryProvider -> SummaryProvider fix: relax trait bounds where possible
lint: clippy
test: add concurrent Summary metric test
mempirate
left a comment
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.
LGTM, some minor things but approved. I would like to see this tested in the real world before we do a release, can work on that this week in one of the projects.
| } | ||
| } | ||
|
|
||
| // TODO: switch to FixedVec |
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.
FixedVec because we know the number of observations before committing I suppose? Would it be more efficient?
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.
Yes, Fixed in terms of fixed capacity https://docs.rs/orx-concurrent-vec/latest/orx_concurrent_vec/struct.FixedVec.html
The number of measurements will be at most batch size (or a few over those) so we could preallocate the required capacity instead of having the ConcurrentVec grow
thedevbirb
left a comment
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.
Minor things
| &self, | ||
| maybe_buckets: Option<syn::Expr>, | ||
| maybe_quantiles: Option<syn::Expr>, | ||
| ) -> Result<Partitions> { |
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.
Can you elaborate more on how you preserve the semantics better?
| /// A simple Summary metric implementation | ||
| #[derive(Debug, Clone)] | ||
| pub struct SimpleSummary { |
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.
What does "Simple" mean here? Overall the distinction between rolling and simple isn't super clear, I have a rough idea but I want to be sure.
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.
Added a comment, but it's to differentiate it from Rolling.
The rolling one has a configured expiry duration so values past that duration are expired and removed, thus not returned from the snapshot, and thus not used for quantile computation
| if matches!(e, prometheus::Error::AlreadyReg) { | ||
| registry | ||
| .unregister(boxed.clone()) | ||
| .unwrap_or_else(|_| panic!("Failed to unregister metric {id}")); |
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.
Is it okay to panic here because this is code running at compile time?
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 is not running at compile time, it's run during the metric initialization (when building it)
I copied it from the other metrics, which do the same.
This scenario can happen if the collector was not registered, which is also not possible because we just got "AlreadyReg" error, indicating that it was indeed registered.
In the same way, the register function errors when the collector was already registered, which we just unregistered.
Looking inside the function, it seems like the only other error (from register) other than AlreadyReg would just be a configuration error: descriptor with same name but different help, for example, which is not something recoverable really
refactor: generic extraction method for readability docs: explain RollingSummary docs: explain SimpleSummary fix(rolling): return total count in snapshot
thedevbirb
left a comment
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.
Great job!
Closes #20
This PR also includes some other small improvements:
helpstring when using prometric-deriveTODO: