|
|
|
// Copyright 2015 The Prometheus Authors
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package storage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/prometheus/common/model"
|
|
|
|
)
|
|
|
|
|
|
|
|
// SampleAppender is the interface to append samples to both, local and remote
|
|
|
|
// storage. All methods are goroutine-safe.
|
|
|
|
type SampleAppender interface {
|
|
|
|
// Append appends a sample to the underlying storage. Depending on the
|
|
|
|
// storage implementation, there are different guarantees for the fate
|
|
|
|
// of the sample after Append has returned. Remote storage
|
|
|
|
// implementation will simply drop samples if they cannot keep up with
|
|
|
|
// sending samples. Local storage implementations will only drop metrics
|
|
|
|
// upon unrecoverable errors.
|
|
|
|
Append(*model.Sample) error
|
|
|
|
// NeedsThrottling returns true if the underlying storage wishes to not
|
|
|
|
// receive any more samples. Append will still work but might lead to
|
|
|
|
// undue resource usage. It is recommended to call NeedsThrottling once
|
|
|
|
// before an upcoming batch of Append calls (e.g. a full scrape of a
|
|
|
|
// target or the evaluation of a rule group) and only proceed with the
|
|
|
|
// batch if NeedsThrottling returns false. In that way, the result of a
|
|
|
|
// scrape or of an evaluation of a rule group will always be appended
|
|
|
|
// completely or not at all, and the work of scraping or evaluation will
|
|
|
|
// not be performed in vain. Also, a call of NeedsThrottling is
|
|
|
|
// potentially expensive, so limiting the number of calls is reasonable.
|
|
|
|
//
|
|
|
|
// Only SampleAppenders for which it is considered critical to receive
|
|
|
|
// each and every sample should ever return true. SampleAppenders that
|
|
|
|
// tolerate not receiving all samples should always return false and
|
|
|
|
// instead drop samples as they see fit to avoid overload.
|
|
|
|
NeedsThrottling() bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fanout is a SampleAppender that appends every sample to each SampleAppender
|
|
|
|
// in its list.
|
|
|
|
type Fanout []SampleAppender
|
|
|
|
|
|
|
|
// Append implements SampleAppender. It appends the provided sample to all
|
|
|
|
// SampleAppenders in the Fanout slice and waits for each append to complete
|
|
|
|
// before proceeding with the next.
|
|
|
|
// If any of the SampleAppenders returns an error, the first one is returned
|
|
|
|
// at the end.
|
|
|
|
func (f Fanout) Append(s *model.Sample) error {
|
|
|
|
var err error
|
|
|
|
for _, a := range f {
|
|
|
|
if e := a.Append(s); e != nil && err == nil {
|
|
|
|
err = e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// NeedsThrottling returns true if at least one of the SampleAppenders in the
|
|
|
|
// Fanout slice is throttled.
|
|
|
|
func (f Fanout) NeedsThrottling() bool {
|
|
|
|
for _, a := range f {
|
|
|
|
if a.NeedsThrottling() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|