-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Parse created timestamps from OpenMetrics-Text format #13506
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -219,9 +219,28 @@ func (p *OpenMetricsParser) Exemplar(e *exemplar.Exemplar) bool { | |
| return true | ||
| } | ||
|
|
||
| // CreatedTimestamp returns nil as it's not implemented yet. | ||
| // TODO(bwplotka): https://github.com/prometheus/prometheus/issues/12980 | ||
| // For OpenMetrics text, the created timestamp is exposed as it was an extra metric. | ||
| // The difference between an usual metric and the created timestamp is that for | ||
| // the created timestamp, the metric name ends with "_created". | ||
| // | ||
| // Created timestamps are always exposed right after the metric they are | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Is that part of the OpenMetrics spec? I think in practice I have only seen
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at the example in their specification, I see _created lines for each metric point and not MetricFamily. In the section Overall Structure, we have one created line for
Do you mean for the same MetricPoint? All the examples I've seen have the _created line as the last line of a MetricPoint, but I couldn't find anything in the spec saying that this order is a MUST. I'm not sure if we should expect something different 🤔
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're correct, I meant MetricPoint, sorry! I agree that all of the samples show
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 😭😭😭😭 That makes things so much more complicated 🥲
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it might be worth getting an opinion from someone more involved in OpenMetrics than myself as I agree, it would be nice not to have to worry about the order!
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not more involved in OpenMetrics, but I think it's totally fine that an experimental feature relies on this accidental property.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, the order of _created is not guaranteed to be the last. But also I don't understand you worries @ArthurSens -- if it's last we already have the problem of having to "buffer" previous samples related to the _created metric which is potentially at the end. So it does not matter if it's end, middle or first. We still have to buffer samples (and corresponding series, which should be the same) no matter what, so we can add potential 0 sample OR in future add it to metadata. Right now CreatedTimestamp() returns number ONLY when parser hits _created metric, which is clearly not enough for OM as we already written sample for related series no? We have to change bit this logic to e.g. buffer series in (OpenMetrics parsing only). To me that means e.g. having different
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not 100% sure yet(doing research at the moment), but I believe all official client libraries that offer OpenMetrics support today expose Expecting different order for the _created lines will make the code a lot more complex, we could make reviews easier if we split this up in different work streams :)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can, but my point stays Arthur, how it makes the code more complex if it's before , in the middle or after the line? The main challenge is that you have to keep buffering samples somewhere BEFORE appending until you know that _created line. This is because we try to be lean and stream parsing line by line. This is the main complexity to the code, not searching where that line is or something 🤔 I also don't see that buffering in this PR, can you elaborate a planned algorithm for parsing with OM text then you envision (with and without assumption of _created line being last)? Maybe in pseudocode here? |
||
| // associated with. The parser cannot be used for such verification, so it is expected | ||
| // that the caller knows the order of the metrics and calls this function accordingly. | ||
| func (p *OpenMetricsParser) CreatedTimestamp() *int64 { | ||
| if p.mtype == model.MetricTypeGauge || | ||
| p.mtype == model.MetricTypeInfo || | ||
| p.mtype == model.MetricTypeStateset || | ||
| p.mtype == model.MetricTypeUnknown || | ||
| p.mtype == "" { | ||
| return nil | ||
| } | ||
| var labels labels.Labels | ||
| p.Metric(&labels) | ||
| name := labels.Get(model.MetricNameLabel) | ||
| if name[len(name)-8:] == "_created" { | ||
| ct := int64(p.val) | ||
| return &ct | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,7 +64,10 @@ _metric_starting_with_underscore 1 | |
| testmetric{_label_starting_with_underscore="foo"} 1 | ||
| testmetric{label="\"bar\""} 1 | ||
| # TYPE foo counter | ||
| foo_total 17.0 1520879607.789 # {id="counter-test"} 5` | ||
| foo_total 17.0 1520879607.789 # {id="counter-test"} 5 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's change order of _created to explictly show (and test) how it will be handled. |
||
| foo_created 1000 | ||
| foo_total{a="b"} 17.0 1520879607.789 # {id="counter-test"} 5 | ||
| foo_created{a="b"} 1000` | ||
|
|
||
| input += "\n# HELP metric foo\x00bar" | ||
| input += "\nnull_byte_metric{a=\"abc\x00\"} 1" | ||
|
|
@@ -225,6 +228,14 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5` | |
| lset: labels.FromStrings("__name__", "foo_total"), | ||
| t: int64p(1520879607789), | ||
| e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "counter-test"), Value: 5}, | ||
| ct: 1000, | ||
| }, { | ||
| m: "foo_total{a=\"b\"}", | ||
| v: 17, | ||
| lset: labels.FromStrings("__name__", "foo_total", "a", "b"), | ||
| t: int64p(1520879607789), | ||
| e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "counter-test"), Value: 5}, | ||
| ct: 1000, | ||
| }, { | ||
| m: "metric", | ||
| help: "foo\x00bar", | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.