Hi, I forgot to post the link to the PR implementing this proposal in an attempt to show the required changes, here it is: https://github.com/prometheus/prometheus/pull/7159
Coming back to the concerns regarding error in no-error cases and how would it work in case of failed scrapes: Inside TSDB: The error created during series creation would be transported back to the Add <https://github.com/prometheus/prometheus/blob/746820ede8c7c230477f7730a0b74459f7ff84c0/tsdb/head.go#L931> method which already returns errors. Outside TSDB where Add is used: In the case of Prometheus, it is a no-op, hence there no change. And it largely depends on how the external user handles the errors if we are talking about outside Prometheus. Additionally, I don't see this being used along with scraping by an external user. But talking about scraping anyway, it would be a rollback when an error is returned. In this case the series won't be created and we have cases where series are not created in `Add` (empty label set or duplicate labels). Any problems in semantics here? Thanks, Ganesh On Wednesday, April 22, 2020 at 2:36:13 PM UTC+5:30, GANESH VERNEKAR wrote: > > > > On Tuesday, April 21, 2020 at 9:39:49 PM UTC+5:30, Brian Brazil wrote: >> >> On Tue, 21 Apr 2020 at 16:48, 'GANESH VERNEKAR' via Prometheus Developers >> <[email protected]> wrote: >> >>> >>> >>> On Tuesday, April 21, 2020 at 8:59:12 PM UTC+5:30, Brian Brazil wrote: >>>> >>>> On Tue, 21 Apr 2020 at 15:17, 'GANESH VERNEKAR' via Prometheus >>>> Developers <[email protected]> wrote: >>>> >>>>> Hi All, >>>>> >>>>> I would like to propose a callback for the TSDB for series creation >>>>> and deletion. This would help external projects like Cortex and Thanos in >>>>> implementing limits on series while having no performance impact on >>>>> Prometheus with minimal code addition. >>>>> >>>>> The callback would look something like this (names TBD) with no >>>>> performance impact on TSDB. >>>>> >>>>> >>>>> type SeriesLifecycleCallback interface { >>>>> >>>>> PreCreationCallback(labels.Labels) error >>>>> >>>>> PostCreationCallback(labels.Labels) >>>>> >>>>> PostDeletionCallback(labels.Labels) >>>>> >>>>> } >>>>> >>>>> *1. SeriesLifecycleCallback* >>>>> >>>>> It would be a part of DB.Options >>>>> <https://github.com/prometheus/prometheus/blob/fc3fb3265a0f0061d07d0bf5fb4103e2144565b2/tsdb/db.go#L73-L116> >>>>> >>>>> *2. PreCreationCallback* >>>>> >>>>> It would be called just before holding the lock here >>>>> <https://github.com/prometheus/prometheus/blob/fc3fb3265a0f0061d07d0bf5fb4103e2144565b2/tsdb/head.go#L1654>. >>>>> >>>>> And if the method returns an error, it means we don’t want to create a >>>>> new >>>>> series. >>>>> >>>>> Further the hashes would be checked as usual >>>>> <https://github.com/prometheus/prometheus/blob/fc3fb3265a0f0061d07d0bf5fb4103e2144565b2/tsdb/head.go#L1656-L1659>, >>>>> >>>>> and if we reach the step of adding a new hash >>>>> <https://github.com/prometheus/prometheus/blob/fc3fb3265a0f0061d07d0bf5fb4103e2144565b2/tsdb/head.go#L1660>, >>>>> >>>>> it would be either executed or skipped based on the result of >>>>> `PreCreationCallback`. >>>>> >>>>> If the series creation was skipped, the error returned by >>>>> `PreCreationCallback` would be propagated back into the call stack and >>>>> the >>>>> `Add` or `AddFast` method would finally return back the error. (This >>>>> means >>>>> additional return values for the methods in that call stack). >>>>> >>>>> *3. PostCreationCallback* >>>>> >>>>> This would be called after releasing the lock here >>>>> <https://github.com/prometheus/prometheus/blob/fc3fb3265a0f0061d07d0bf5fb4103e2144565b2/tsdb/head.go#L1661> >>>>> >>>>> letting the caller know that the series was created. >>>>> >>>>> *4. PostDeletionCallback * >>>>> >>>>> >>>>> It would be called after deleting a series during garbage collection here >>>>> (after unlocking) >>>>> <https://github.com/prometheus/prometheus/blob/fc3fb3265a0f0061d07d0bf5fb4103e2144565b2/tsdb/head.go#L1625> >>>>> >>>>> so that external projects can do the bookkeeping. >>>>> >>>>> ---- >>>>> >>>>> In the context of Prometheus, the interface would be a noop, hence no >>>>> performance impact. >>>>> >>>> >>>> It'd still cost a few cycles. >>>> >>> >>> But it would be very less to even notice. >>> >>> >>>> >>>>> >>>>> *Some reasoning behind the design decisions and what guarantees it >>>>> provides:* >>>>> >>>>> The idea was to avoid having the callbacks inside the locked section >>>>> which could lead to performance degradation. Hence the Series creation >>>>> callback was split into 2 methods. PreCreationCallback method tells >>>>> whether to create the series if we need to create and the next method >>>>> `PostCreationCallback` to let the user know if it was created, so that >>>>> appropriate bookkeeping can be done. >>>>> >>>>> Since all the callbacks happen outside the locks (even if it was >>>>> inside the lock, there could be concurrent calls for different shards of >>>>> the stripe series), the user can expect some soft consistencies here. For >>>>> example, the PreCreationCallback could be called concurrently by >>>>> multiple series creation when you are at the edge of the series limit and >>>>> all the series creation would be allowed, which might cause the limit to >>>>> cross by a small number. Similarly during the deletion phase: some >>>>> creation >>>>> of series would fail as the deletion callback is called a little later. >>>>> Hence the user is required to expect soft consistencies while using these >>>>> callbacks. >>>>> >>>>> What do you all think about this addition in TSDB? >>>>> >>>> >>>> This seems to require adding error handling for cases where Prometheus >>>> cannot have errors, what happens to a scrape or rule evaluation when this >>>> fails? >>>> >>> >>> The Add >>> <https://github.com/prometheus/prometheus/blob/4b5e7d4984a135abd3729b9a2a5904336d35bc21/tsdb/head.go#L931> >>> >>> and AddFast >>> <https://github.com/prometheus/prometheus/blob/4b5e7d4984a135abd3729b9a2a5904336d35bc21/tsdb/head.go#L957> >>> >>> methods already returns an error. So failure in series creation would >>> follow the same procedure. But thinking about it more, it will be a no-op >>> for Prometheus, and I don't think the external users who would use this >>> feature will have scraping in it (considering it as a "TSDB" package and >>> not "Prometheus" package). >>> >>> >>>> I'm also not sure it's considering that the semantics of how this is >>>> all managed inside the tsdb is not what you might expect. For example a >>>> failed scrape due to hitting the sample limit can still cause series to be >>>> created, which usually doesn't come up but might now. >>>> >>> >>> Yes, all the changes in TSDB are not totally explored yet, I will work >>> on a draft to see what all needs changing. >>> >> >> >> >>> Additionally, series is still created currently if the appender Commit() >>> fails (a failed scrape?). >>> >> >> A failed scrape would be a Rollback. A WAL error is what would cause a >> Commit to fail, which is likely a full filesystem. >> > > Yes, but series is still created in case of Rollback and not deleted till > next compaction. > > >> -- >> Brian Brazil >> www.robustperception.io >> > -- You received this message because you are subscribed to the Google Groups "Prometheus Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/prometheus-developers/82b7365a-4669-4346-8349-250801805829%40googlegroups.com.

