-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Optionally add OM unit #1392
Optionally add OM unit #1392
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]>
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]>
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]>
Hey @vesari , just passing by to ask if there is anything we could do to unblock you 👋 |
@ArthurSens hello! I think I'm just using a Go version which is too new, I plan on fixing that later today. Thanks a lot for checking on me, much appreciated! :) |
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]>
@ArthurSens hello again! Here are a few considerations to give you some insight about what I’ve done here and why. The lint was failing on a supposedly unused test function unrelated to my changes ( I made the changes needed where an OM format can be passed to Also, so far I haven’t added any new tests to Lastly, I happened to push a lot of commits, let me know if you want me to rebase and squash them. As per usual, many thanks for your time and help! :) |
Oh sorry for the silence here, somehow I missed your last comment.
Yeah, that's a problem actually. We promise support for the 3 latest go versions, so we can't bump our go version to 1.21 until mid-August when go 1.23 is released. I've started conversations about how we can improve this situation with common.
This is another problem that I've been delaying for way too long 😬 From my understanding it doesn't block PRs though. But anyway, I'll try to get back to this soon, no need to remove it now :) Regarding the changes that are related to OpenMetrics units, I haven't taken a deep look yet 😬. I'm mostly concerned with enabling the PR first and will review the changes once we solve all the blockers |
Thanks a lot for the detailed update! Much appreciated |
Hi @vesari, all blockers have been resolved finally :) The unused function is now used, and we can update prometheus/common without giving up support of go 1.20. If you rebase your PR it should be fine :) |
prometheus/promhttp/http.go
Outdated
// If true, WithUnit adds the unit to the encoder options, ultimately allowing the | ||
// unit into the final output, provided that EnableOpenMetrics is also true. | ||
WithUnit bool |
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 #1408, we're changing a bit the structure of the HandlerOpts regarding OpenMetrics functionality. We'll probably want something similar 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.
@ArthurSens I made some changes to my code accordingly, but I think it would be better for your PR to be merged before mine, as yours has already been approved and also because in yours you explain the rationale behind the new HandlerOpts struct and what options to prefer. I can then take it from there and finish mine. What do you think? :)
Awesome! Thank you very much! I'm on it. |
Signed-off-by: Arianna Vespri <[email protected]>
Signed-off-by: Arianna Vespri <[email protected]>
Signed-off-by: Arianna Vespri <[email protected]>
@ArthurSens , I've marked this as "ready for review", but I'm still assuming your PR should be merged first? |
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 this!
I don't think this PR is blocked on #1408, but I think I would challenge adding units in this way (or adding units at all).
First of all, we can't change NewDesc
, it's breaking change.
Then the explicit unit in v2.NewDesc and all metric type constructors' options. Essentially, are we sure asking users to add unit to all their definitions (given majority of the ecosystem metrics have unit in the metric name already) is a good use of their time for the benefit (and what is the benefit actually?)
BTW @vesari or anyone, feel free to challenge me! I might miss some use cases etc! 🤗
So there are two questions to answer:
- What's the benefit of having UNIT entry in metadata for OpenMetrics? Essentially what users would gain by using OpenMetrics with Units metadata entry? Right now, I see near zero value 🤔
a. They would gain "formal compatibility with OpenMetrics 1.0, which means little (no scraper blocks client_golang OpenMetrics at the moment, so what's the point?) and we break compatibility for reasons (we think it would be damaging for Go Prometheus ecosystem to add e.g. _created metrics by default).
b. Some third party systems would use it. Can we wait for actual use cases come to us? or maybe you have use case?
Wonder, what's your motivation to add units?
- What's the additional friction for defining metrics. How we can reduce it or automate it. Howe can reduce the things they need to touch, not increase in their code?
Just looking on changing client golang metrics, we have dozens of changes like this:
Also:
Now, do we think ALL of 118,491 repositories will check and be happy with extra line to every metric definition that literally duplicate a string. That's like billion code lines in total if everyone would just add one line to every metric with some unit across all our users, JUST in open source. We have to be careful here.
One idea would be to work on some autodetection mechanism that would try to detect units in metric names IF somebody enabled UNITs AND OpenMetrics format 🤔 Ideally we could have some bigger design/proposal for it. However, first question - remains. Do we need UNIT metadata entry?
To sum up, sorry for those challenging questions. Your code is top quality, thanks for massive work on this. It's just a controversial change a bit, and we have large user base, so we have to be more careful here 🤗 DMed you on Slack too, feel bad a bit I didn't respond earlier.
@@ -28,7 +28,7 @@ jobs: | |||
- name: install Go | |||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 | |||
with: | |||
go-version: 1.20.x | |||
go-version: 1.21.x |
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.
Next time, this probably should be done in a separate PR 🤗
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 wonder why this change was even needed 😬, could you explain why you decided to bump the go version 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.
Same as with the go.mod
below. Just some change I should have reverted, sorry.
@@ -381,6 +387,14 @@ type HandlerOpts struct { | |||
ProcessStartTime time.Time | |||
} | |||
|
|||
type OpenMetricsOptions struct { | |||
Enable bool |
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.
Perhaps we could remove this field and use OpenMetricsOptions *OpenMetricsOptions
to ensure it's optional? We cannot remove EnableOpenMetrics
anyway so we could still use that, OR when OpenMetricsOptions is allocated assume OM is enabled? 🤔
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.
Here I was kinda tying the possibility of enabling the optional unit to OM been already negotiated as the output format, but maybe there are better ways to ensure that.
@@ -75,8 +77,8 @@ type Desc struct { | |||
// | |||
// For constLabels, the label values are constant. Therefore, they are fully | |||
// specified in the Desc. See the Collector example for a usage pattern. | |||
func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc { | |||
return V2.NewDesc(fqName, help, UnconstrainedLabels(variableLabels), constLabels) | |||
func NewDesc(fqName, help, unit string, variableLabels []string, constLabels Labels) *Desc { |
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.
Unfortunately this is a breaking change. We can't change this function.
Not sure how to solve it. Probably NewDescWithUnit, or changing v2 only would make sense.
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.
Agreed, we can't make this change.
I wonder what would be a good option though, maybe something like below?
func (d *Desc) WithUnit(u string) *Desc {
d.unit = u
return d
}
A new function NewDescWithUnit
also sounds doable, but honestly, a v2 would be the cleaner option. I'm not sure how viable v2 is though
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.
Sure, I'll revert the breaking changes and explore the alternatives you both suggested.
I realized we already kind of agreed to supporting this... #684 so probably too late to challenge it cc @beorn7 @ArthurSens - do you remember what's the benefit other than "compatibility"? The friction comment and breaking change stays. I feel we could do better than adding Perhaps some automation AND clear guidance e.g. in comment to NOT add it if you have correct unit in name would help? |
Co-authored-by: Bartlomiej Plotka <[email protected]> Signed-off-by: Arianna Vespri <[email protected]>
@bwplotka thanks, I'll await @beorn7 and @ArthurSens 's feedback on your questions, as they know the original motivation :) |
At this point, I believe the main benefit is only compatibility with OpenMetrics 1.0, yes. I totally understand that OpenMetrics 1.0 has many details that hinge adoption in the Prometheus ecosystem, but I think we can't ignore that OM 1.0 exists and is used out there. Prometheus already parses OM units, and stores it as metadata. So my rationale to accept this was to finally close the gap between go applications that wanted this information in Prometheus. With that said, I admit I'm not aware of how units are used in Prometheus besides easy identification when a human reads PromQL. I was not part of the team when OpenMetrics became a thing, but I had the impression that units were added to the data model for a reason, and that work was being done (or planned to) to make use of units when making operations between metrics that were exposed with different units, e.g. |
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.
If we decide to support units, let's think of alternative that isn't breaking changes to downstream projects :)
func NewInfoVec(name, help string, labelNames []string) *InfoVec { | ||
desc := prometheus.NewDesc(name, help, labelNames, nil) | ||
func NewInfoVec(name, help, unit string, labelNames []string) *InfoVec { | ||
desc := prometheus.NewDesc(name, help, unit, labelNames, nil) |
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.
Similar problem here, we can't change Public function's signatures
go 1.20 | ||
go 1.21 |
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 we want to keep 1.20 until the next go release
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.
Oops. Yes, absolutely. Just a leftover from when I reverted the changes I had made before common
was fixed in this sense.
Of course! I'll await your decision whether to support them and, if so, I'll be happy to continue working on it the way you suggested :) |
It's hard for me to give a fair judgement here (because of my difficult history with OM). Having said that, the OM approach to units strikes me as weird. I understand the historical Prometheus approach of "including the unit in the metric name" as a pragmatic solution to the lack of proper metadata support in Prometheus. It should be noted that it always has been just a convention. OM added the unit metadata field, presumably because others asked for it (the OTel data model didn't exist back then, but I assume that the presence of a unit field in OTel comes from the same school of thinking). Now you might think, if OM has it as an explicit field, you don't have to include it in the metric name anymore. But OM did the opposite: If there is a unit field, the same string MUST be in the metric name, otherwise it is not valid OM. Personally, I think it should be possible to include the unit in the metric name (for those that like that for all the situation where you do not want to lookup the metadata even if you could), but given that others want to live in a world where metadata is always available at your fingertips, enforcing it in the metric name feels redundant. Sadly, OTel took its guidance for Prometheus compatibility from OM, so the way the OTel data model is converted to Prometheus is already following the OM requirements, although there was never a Prometheus consensus about it. Looping back to the question: How should we deal with the situation in client_golang? Given how far unit support has already seeped into various parts of the wider ecosystem, it's tough to say "this is all f*** up, let's just ignore it". How "1st class" adding the unit should be, is up to debate. I definitely wouldn't require all users to now add a unit. It should be an option for those that want it. WRT to |
Thank you all very much for your considerations and suggestions! In order not to enforce that the unit is also in the metric name when the unit field is populated, the logic in |
To be clear: @ArthurSens @bwplotka @kakkoyun should make the call here. I'm just providing my personal context. |
Hi @vesari! The team met recently and one of the things we discussed was whether we accept OpenMetrics units or not. Reading the OpenMetrics specification, we can read[1][2]:
We clearly understand that units are required by OpenMetrics 1.0, and we clearly understand that units must be used as metric name suffixes. However, at this point, if we accept this the only benefit would be to say "We're OpenMetrics 1.0 compatible". Being OpenMetrics 1.0 compatible is not a bad thing per se, but Prometheus hasn't used the Unit metadata for anything yet, so it brings Client_golang users little benefit while making our API a bit more complex. If in the future Prometheus introduces the usage of Unit metadata, e.g. to properly sum metrics with different but compatible units (one in seconds and the other in milliseconds), we'd be happy to resurrect this. In the name of the team, we apologize for taking this long to make a decision. Your work was quite involved, spreading contributions across multiple repositories and communicating with several stakeholders. We'd be happy to continue working with you if that's also of your interest :) |
Maybe we could start brainstorming how to use the unit metadata in Prometheus? Although this would be a high-complexity project that I would also need a lot of time to understand properly😬 |
@ArthurSens, no worries at all, I totally understand. Of course I’d be delighted to continue working with the team, thanks for suggesting that! |
Either this or anything the team deem useful. Whatever you think needs attention, I’ll be happy to work on :) Feel free to DM me on Slack if necessary. Thank you! |
As agreed with @bwplotka, we want to add units eventually, but this needs more thought on how to avoid adding significant boilerplate to all users for that; help wanted, closing for now. |
This PR adds support for unit for Open Metrics. It is ready for review, but not ready to merge (see my long comment below). Fixes #684.