Repository navigation
Conversation
a080d34 to
1411e64
Compare
8db2179 to
59397b4
Compare
Define two progressive modes for io.prometheus.write.v2.Request: stateless (requiring Exemplars attached to samples/histograms and Histogram messages for histograms) and stateless-typed (extending stateless with mandatory Metadata.type and start_timestamp on cumulative/delta metric types). Signed-off-by: Bartek Plotka <bwplotka@gmail.com>
59397b4 to
b865bfd
Compare
| #### Invalid Samples | ||
|
|
||
| Receivers MAY NOT support certain metric types or samples (e.g. a Receiver might reject sample without metadata type specified or without start timestamp, while another Receiver might accept such sample.). It’s up to the Receiver what sample is invalid. Receivers MUST return a [400 HTTP Bad Request](https://www.rfc-editor.org/rfc/rfc9110.html#name-400-bad-request) status code for write requests that contain any invalid samples unless the [partial retriable write](#retries-on-partial-writes) occurs. | ||
| Receivers SHOULD reject samples that violate this specification or the negotiated [mode](#modes). Receivers MAY reject samples that violate receiver-specific limits and gaps (such as not supporting native histograms, or label count or length limits). Receivers MUST return a [400 HTTP Bad Request](https://www.rfc-editor.org/rfc/rfc9110.html#name-400-bad-request) status code for write requests that contain any invalid samples unless the [partial retriable write](#retries-on-partial-writes) occurs. |
There was a problem hiding this comment.
This is to address here some discussions points of @krajorama
1. Receiver strict validation of spec and mode (IMO "SHOULD" not "MUST")
The existing spec was relaxed on this. Receiver are not responsible for validating the spec (e.g. ST on gauges), although they MAY. Somewhat exception are core elements like Sample, Histogram and Example (response headers are MUST).
Rationales for keeping MAY for both spec and mode validation:
a. Forward compatibility:
- Proto allows us to add new fields etc. Expecting receiver to validate would mean new fields would be a breaking change
- Similarly we wouldn't be able to add new modes as technically old receivers would need to add special validation per mode. Our goal is to ensure generic receiver implementation is possible - one that can support all modes similar to HTTP Media Type Profiles (RFC 6906):
A profile parameter on Content-Type constrains what the sender puts on the wire so profile-aware receivers can rely on it, while explicitly guaranteeing that any generic receiver of the base media type can accept the payload even if it ignores the profile's extra semantics.
b. Makes RW2 adoption on receive harder (e.g. my RW2 sink that only checks certain things is not "compliant").
c. Efficiency - burning CPU on things you don't care about?
d. Adoption: If client ever supports stateless - receiver might want to accept it and partially reject untyped metrics.
As a result, it's all SHOULD here.
2. Receiver accepting a mode means it will use all it's data (IMO that's explicitly NOT an intention)
We mentioned this concept that sender might want to know that e.g. if ST is sent and stateless-typed is used and receiver returns 200 code it means ST is actually used for querying (!).
This has some uses, but I think it's hard to rely on, plus all the problems above.
So we don't expect that - modes are to:
- Simplify communication between sender and receiver (e.g. simplify sender configuration, reject undesired modes early on receive, clearly document which mode is how expensive)
- Help with adoption of more advanced modes (e.g. letting sender know that some receivers will only support certain mode, monitoring mode adoption etc)
|
Proposed implementation of those modes in Prom: |
dashpole
left a comment
There was a problem hiding this comment.
This split makes sense to me
…tart_timestamp Signed-off-by: Bartek Plotka <bwplotka@gmail.com>
| * Use content type of `Content-Type: application/x-protobuf;proto=io.prometheus.write.v2.Request;mode=stateless`. | ||
| * Ensure all of the following for every `TimeSeries` in a `Request`: | ||
| * `Exemplar`s MUST only be sent on a `TimeSeries` that also contains at least one element in `samples` or in `histograms`. Exemplar-only `TimeSeries` messages MUST NOT be sent. | ||
| * Histograms MUST use the `Histogram` message (e.g. using Native Histograms with Custom Buckets instead of classic histogram `_bucket`, `_sum`, and `_count` float `Sample` series). |
There was a problem hiding this comment.
nit: if the type is not set, it's impossible to validate this, which questions the stateless name a little bit and the usefulness of this mode :(
There was a problem hiding this comment.
Well, not if we specify a clear heuristic e.g. _bucket, _sum, _count UNTYPED can be rejected. But yes, this is probably the biggest downside of this solution.
There was a problem hiding this comment.
_sum and _count can be summary as well, so nope. This is what we ran into when migrating to native histograms internally, we couldn't tell from PromQL queries alone what the type was, so we had to cross reference with the source code all the time.
There was a problem hiding this comment.
I'm a bit naive on this front, are summaries something we still want to support to the point that this would be a blocker beyond updating the spec to say they get dropped too if they are untyped?
| * Satisfy all `TimeSeries` requirements of [`stateless` mode](#stateless-mode). | ||
| * Ensure all of the following for every `TimeSeries` in a `Request`: | ||
| * `Metadata.type` MUST be specified and MUST NOT be `METRIC_TYPE_UNSPECIFIED` (`0`). | ||
| * `start_timestamp` MUST be set (non-zero) on every `Sample` and `Histogram` (except stale markers) for cumulative or delta metric types (`METRIC_TYPE_COUNTER`, `METRIC_TYPE_HISTOGRAM`, as well as `METRIC_TYPE_SUMMARY` `_sum` and `_count` `Samples`). |
There was a problem hiding this comment.
note: I'm unsure about this combined with metadata. As we said, maybe sending ST with every sample isn't a good idea for bandwidth when it comes to cumulative metrics. But I'm unsure about the actual overhead.
There was a problem hiding this comment.
Well, it's what some backends needs - true ST on cumulatives.
In Prometheus ecosystem I can imagine stateless + metric types (no ST) is the future (aka 3.0)
|
Practically, when a client sends the new Which means that the user needs to ask the admin of the receiver whether the check was actually performed. Consider returning |
…tion, and metric types Signed-off-by: Bartek Plotka <bwplotka@gmail.com>
I don't think we should add a response header for this:
|
| <!--- | ||
| Rationales: https://github.com/prometheus/proposals/blob/alexg/remote-write-20-proposal/proposals/2024-04-09_remote-write-20.md#no-new-compression-added--yet- | ||
| --> | ||
| Content encoding request header MUST follow [the RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-content-encoding). Senders MUST use the `snappy` value. Receivers MUST support `snappy` compression. New, optional compression algorithms might come in 2.x or beyond. |
There was a problem hiding this comment.
Do we want to do anything about opening up compression options for rc6 or leave that for a different RC?
|
|
||
| #### Modes | ||
|
|
||
| By default (when no `;mode=` parameter is set), `io.prometheus.write.v2.Request` keeps several structural and metadata rules optional (`SHOULD` or `MAY`) so Senders can forward any scraped metric without data loss or conversion overhead. However, some common stateless or strongly typed Receivers cannot ingest all the data e.g. detached exemplars, classic histogram series or untyped metrics. |
There was a problem hiding this comment.
WDYT about naming the default mode stateful? This way every mode has a named option and if we move the default at a later time there's still a named option for people to fall back on.
I think being able to explicitly configure the mode could also be helpful vs needing to know implicitly what no mode means.
|
|
||
| Senders SHOULD support `stateless` and `stateless-typed` modes. Senders MAY operate in either mode behind configuration or by default. | ||
|
|
||
| Receivers MAY accept any valid `io.prometheus.write.v2.Request` regardless of mode, require at least `stateless` mode, or require `stateless-typed` mode only. If rejected, [415 HTTP Unsupported Media Type](https://www.rfc-editor.org/rfc/rfc9110.html#name-415-unsupported-media-type) MUST be used. |
There was a problem hiding this comment.
https://github.com/prometheus/docs/pull/3142/changes#diff-fb08fe6850c73166c5ad591d90f78aee4c90986316885ec04d0942ee871640b9R199 mentions a sender can retry when they get a 415 to try to find something that works. We could return the supported content types in the response so senders aren't having to iterate and guess. Doing this is probably enough to avoid needing an ahead of time content negotiation.
Alternative to #3129.
Specify two progressive modes (
statelessandstateless-typed) forio.prometheus.write.v2.Requestin Remote-Write2.0-rc.6, following the Prometheus Dev Summit consensus and RFC 9413.By default, when no
;mode=parameter is set onContent-Type: application/x-protobuf;proto=io.prometheus.write.v2.Request, all field permutations permitted by the base specification may be sent.2.0-rc.6adds two optional, progressive modes where sendersMUSTguarantee:statelessmode (Content-Type: application/x-protobuf;proto=io.prometheus.write.v2.Request;mode=stateless):Exemplars are attached to aTimeSeriesthat contains at least one sample or histogram, so no exemplar-onlyTimeSeriesare sent.Histogrammessage, so classic histograms are sent as NHCB instead of_bucket,_sum, and_countfloat series.stateless-typedmode (Content-Type: application/x-protobuf;proto=io.prometheus.write.v2.Request;mode=stateless-typed):statelessmode.Metadata.typeis set and notMETRIC_TYPE_UNSPECIFIED.start_timestampis set (non-zero) on every sample and histogram for cumulative and delta metric types (METRIC_TYPE_COUNTER,METRIC_TYPE_HISTOGRAM, andMETRIC_TYPE_SUMMARY_sumand_count).Both modes are optional for senders and receivers and remain valid
io.prometheus.write.v2.Requestpayloads on the wire.Why two progressive modes instead of one mode or separate capabilities?
statelessrules, attaching exemplars to samples or histograms and converting classic histograms to NHCB, are sender-side formatting choices. Any sender such as Prometheus or Alloy can enforce them by configuration alone without dropping data, even when scraping legacy targets.stateless-typedrules,Metadata.typeandstart_timestamp, require every series to have a known metric type and counter start time. When scraping targets that expose untyped metrics or omit_createdtimestamps, a sender can only satisfystateless-typedby synthesizing state, inferring types, or dropping non-conforming series.stateless-typedincludesstatelessbecause receivers that require explicit metric types and start timestamps also require structured histograms and attached exemplars, and validatingstart_timestampalready requires knowingMetadata.type.default<stateless<stateless-typed) give 3 well-defined protocol states rather thanContent-Typematching to a single parameter value, and keepprometheus/compliancetesting linear.