-
Notifications
You must be signed in to change notification settings - Fork 802
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 support for native histograms in OM parser #1040
Add support for native histograms in OM parser #1040
Conversation
Signed-off-by: Arianna Vespri <[email protected]>
Signed-off-by: Arianna Vespri <[email protected]>
Signed-off-by: Arianna Vespri <[email protected]>
Signed-off-by: Arianna Vespri <[email protected]>
Signed-off-by: Arianna Vespri <[email protected]>
Signed-off-by: Arianna Vespri <[email protected]>
…abel set Signed-off-by: Arianna Vespri <[email protected]>
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.
Just a quick read through, but I was thinking maybe we limit the changes in the initial PR to just the parser changes? We could get that in and start iterating on it, and it will then be useful for testing the exposition changes.
prometheus_client/metrics.py
Outdated
@@ -595,6 +595,14 @@ def __init__(self, | |||
registry: Optional[CollectorRegistry] = REGISTRY, | |||
_labelvalues: Optional[Sequence[str]] = None, | |||
buckets: Sequence[Union[float, str]] = DEFAULT_BUCKETS, | |||
# native_hist_schema: Optional[int] = None, # create this dynamically? |
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 the internal code should create the schema, and may even change the schema value on occassion.
Signed-off-by: Arianna Vespri <[email protected]>
I totally agree! |
…nd adapt logic accordigly Signed-off-by: Arianna Vespri <[email protected]>
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.
Nice! I left a handful of comments, they probably don't all need to be addressed in this PR, but could be refactorings in future PRs as well.
Mainly I would like to see as few changes to other files, and especially function signatures, as possible. Even if that means we do some things like skipping values that are histograms for now. That way hopefully no one depends on some code/type changes we might update soon.
prometheus_client/bridge/graphite.py
Outdated
# using a safe float convert on s.value as a temporary workaround while figuring out what to do | ||
# in case value is a native histogram structured value, if that's ever a possibility | ||
output.append(f'{prefixstr}{_sanitize(s.name)}{labelstr} {safe_float_convert(s.value)} {now}\n') |
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.
Graphite doesn't have support for native histograms, if for some reason one shows up in a registry we would probably need to drop it with a warning. For now I would say let's not make any changes here as native histograms will be experimental anyway.
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.
You're absolutely right. The thing is the mypy
linter fails without this change. That's due to the native histogram value being a union. I noticed that only when I pushed the PR for the first 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.
Solved after separating fields
else: | ||
elems = pos_spans_text.split(',') | ||
arg1 = [int(x) for x in elems[0].split(':')] | ||
arg2 = [int(x) for x in elems[1].split(':')] | ||
pos_spans = (BucketSpan(arg1[0], arg1[1]), BucketSpan(arg2[0], arg2[1])) |
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 would avoid the else block and move these into the try block. That keeps all the happy path/text parsing code together.
prometheus_client/registry.py
Outdated
@@ -128,7 +129,7 @@ def _target_info_metric(self): | |||
m.add_sample('target_info', self._target_info, 1) | |||
return m | |||
|
|||
def get_sample_value(self, name: str, labels: Optional[Dict[str, str]] = None) -> Optional[float]: | |||
def get_sample_value(self, name: str, labels: Optional[Dict[str, str]] = None) -> Optional[Union[float, NativeHistStructValue]]: |
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.
Does this need to change yet? It would be nice to have no/minimal public interface changes since we won't be using these in the registry quite yet.
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.
Same as for the Graphite bridge file. mypy
linting fails otherwise.
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.
Solved after separating fields
prometheus_client/samples.py
Outdated
@@ -48,6 +65,6 @@ class Exemplar(NamedTuple): | |||
class Sample(NamedTuple): | |||
name: str | |||
labels: Dict[str, str] | |||
value: float | |||
value: Union[float, NativeHistStructValue] |
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.
Trying to decide if this should be a union or if we should have a separate field for histogram_value
or something like that.
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.
Given the union's "side-effects" in files like registry
etc, maybe it should be a separate field? My initial thinking with the union was to possibly avoid function signature changes I guess, but maybe it wouldn't be that problematic?
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.
Yeah, let's try having a separate Optional field for the native histogram and see what it looks like. It also makes it nice to just check if the value is none or not for if a value is a native histogram.
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 separated them, and added a field for native histogram. I added it for last to minimize the risk of breaking something.
has_gsum = True | ||
if s.value < 0: | ||
has_negative_gsum = True | ||
if len(suffix) != 0: |
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.
Rather than nesting everything further in what about a continue
if len(suffix) is 0
?
prometheus_client/metrics.py
Outdated
# native_hist_schema: Optional[int] = None, | ||
# native_hist_bucket_fact: Optional[float] = None, | ||
# native_hist_zero_threshold: Optional[float] = None, | ||
# native_hist_max_bucket_num: Optional[int] = None, | ||
# native_hist_min_reset_dur: Optional[timedelta] = None, | ||
# native_hist_max_zero_threshold: Optional[float] = None, | ||
# native_hist_max_exemplars: Optional[int] = None, | ||
# native_hist_exemplar_TTL: Optional[timedelta] = None, |
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.
Let's remove these commented out lines until they are actually used.
Thanks for the suggested changes, I'll be working on it :) |
prometheus_client/samples.py
Outdated
length: int | ||
|
||
|
||
class NativeHistStructValue(NamedTuple): |
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.
Just a thought, we could probably just call this NativeHistogram
rather than adding StructValue
. For initial implementation we might want to prefix with _
as well to these new types to make it clear they are internal only and may change. Or add a comment to that effect.
…locks Signed-off-by: Arianna Vespri <[email protected]>
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.
Just a couple of nits/removals and then I think this iteration is ready to merge! Thanks a bunch!
prometheus_client/bridge/graphite.py
Outdated
@@ -92,3 +92,4 @@ def start(self, interval: float = 60.0, prefix: str = '') -> None: | |||
t = _RegularPush(self, interval, prefix) | |||
t.daemon = True | |||
t.start() | |||
|
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.
Nit, could you just remove this line so we don't have a needless diff/history entry?
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.
Done!
prometheus_client/metrics_core.py
Outdated
@@ -236,6 +236,7 @@ def __init__(self, | |||
sum_value: Optional[float] = None, | |||
labels: Optional[Sequence[str]] = None, | |||
unit: str = '', | |||
native_hist_bucket_factor: Optional[float] = None |
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.
🤔 Not sure if we need this here at all (it will need to be in metrics.py
). This function is for custom collectors, and I think if someone is creating a native histogram for that case they will end up needing to define all the spans themself. For now I would say just leave it out.
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, I deleted it.
# check if it's a native histogram with labels | ||
re_nh_without_labels = re.compile(r'^[^{} ]+ {[^{}]+}$') | ||
re_nh_with_labels = re.compile(r'[^{} ]+{[^{}]+} {[^{}]+}$') | ||
print('we are matching \'{}\''.format(text)) |
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.
We should remove the debug printing before merging, there are a couple other lines in this function as well.
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 could see just another one, I hope I removed them all now XD
Signed-off-by: Arianna Vespri <[email protected]>
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.
Thanks for all the work on this!
This PR adds an OM parser for native histograms, as a first step towards the implementation of the following proposal prometheus/proposals#32 . The next steps (as far as this repo is concerned) would be the OM exposition and then obviously the implementation of native histograms generation/writing logic.