github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/util/validation/errors.go (about)

     1  package validation
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/prometheus/common/model"
     9  
    10  	"github.com/cortexproject/cortex/pkg/cortexpb"
    11  )
    12  
    13  // ValidationError is an error returned by series validation.
    14  //
    15  // nolint:golint ignore stutter warning
    16  type ValidationError error
    17  
    18  // genericValidationError is a basic implementation of ValidationError which can be used when the
    19  // error format only contains the cause and the series.
    20  type genericValidationError struct {
    21  	message string
    22  	cause   string
    23  	series  []cortexpb.LabelAdapter
    24  }
    25  
    26  func (e *genericValidationError) Error() string {
    27  	return fmt.Sprintf(e.message, e.cause, formatLabelSet(e.series))
    28  }
    29  
    30  func newLabelNameTooLongError(series []cortexpb.LabelAdapter, labelName string) ValidationError {
    31  	return &genericValidationError{
    32  		message: "label name too long: %.200q metric %.200q",
    33  		cause:   labelName,
    34  		series:  series,
    35  	}
    36  }
    37  
    38  // labelValueTooLongError is a customized ValidationError, in that the cause and the series are
    39  // are formatted in different order in Error.
    40  type labelValueTooLongError struct {
    41  	labelValue string
    42  	series     []cortexpb.LabelAdapter
    43  }
    44  
    45  func (e *labelValueTooLongError) Error() string {
    46  	return fmt.Sprintf("label value too long for metric: %.200q label value: %.200q", formatLabelSet(e.series), e.labelValue)
    47  }
    48  
    49  func newLabelValueTooLongError(series []cortexpb.LabelAdapter, labelValue string) ValidationError {
    50  	return &labelValueTooLongError{
    51  		labelValue: labelValue,
    52  		series:     series,
    53  	}
    54  }
    55  
    56  func newInvalidLabelError(series []cortexpb.LabelAdapter, labelName string) ValidationError {
    57  	return &genericValidationError{
    58  		message: "sample invalid label: %.200q metric %.200q",
    59  		cause:   labelName,
    60  		series:  series,
    61  	}
    62  }
    63  
    64  func newDuplicatedLabelError(series []cortexpb.LabelAdapter, labelName string) ValidationError {
    65  	return &genericValidationError{
    66  		message: "duplicate label name: %.200q metric %.200q",
    67  		cause:   labelName,
    68  		series:  series,
    69  	}
    70  }
    71  
    72  func newLabelsNotSortedError(series []cortexpb.LabelAdapter, labelName string) ValidationError {
    73  	return &genericValidationError{
    74  		message: "labels not sorted: %.200q metric %.200q",
    75  		cause:   labelName,
    76  		series:  series,
    77  	}
    78  }
    79  
    80  type tooManyLabelsError struct {
    81  	series []cortexpb.LabelAdapter
    82  	limit  int
    83  }
    84  
    85  func newTooManyLabelsError(series []cortexpb.LabelAdapter, limit int) ValidationError {
    86  	return &tooManyLabelsError{
    87  		series: series,
    88  		limit:  limit,
    89  	}
    90  }
    91  
    92  func (e *tooManyLabelsError) Error() string {
    93  	return fmt.Sprintf(
    94  		"series has too many labels (actual: %d, limit: %d) series: '%s'",
    95  		len(e.series), e.limit, cortexpb.FromLabelAdaptersToMetric(e.series).String())
    96  }
    97  
    98  type noMetricNameError struct{}
    99  
   100  func newNoMetricNameError() ValidationError {
   101  	return &noMetricNameError{}
   102  }
   103  
   104  func (e *noMetricNameError) Error() string {
   105  	return "sample missing metric name"
   106  }
   107  
   108  type invalidMetricNameError struct {
   109  	metricName string
   110  }
   111  
   112  func newInvalidMetricNameError(metricName string) ValidationError {
   113  	return &invalidMetricNameError{
   114  		metricName: metricName,
   115  	}
   116  }
   117  
   118  func (e *invalidMetricNameError) Error() string {
   119  	return fmt.Sprintf("sample invalid metric name: %.200q", e.metricName)
   120  }
   121  
   122  // sampleValidationError is a ValidationError implementation suitable for sample validation errors.
   123  type sampleValidationError struct {
   124  	message    string
   125  	metricName string
   126  	timestamp  int64
   127  }
   128  
   129  func (e *sampleValidationError) Error() string {
   130  	return fmt.Sprintf(e.message, e.timestamp, e.metricName)
   131  }
   132  
   133  func newSampleTimestampTooOldError(metricName string, timestamp int64) ValidationError {
   134  	return &sampleValidationError{
   135  		message:    "timestamp too old: %d metric: %.200q",
   136  		metricName: metricName,
   137  		timestamp:  timestamp,
   138  	}
   139  }
   140  
   141  func newSampleTimestampTooNewError(metricName string, timestamp int64) ValidationError {
   142  	return &sampleValidationError{
   143  		message:    "timestamp too new: %d metric: %.200q",
   144  		metricName: metricName,
   145  		timestamp:  timestamp,
   146  	}
   147  }
   148  
   149  // exemplarValidationError is a ValidationError implementation suitable for exemplar validation errors.
   150  type exemplarValidationError struct {
   151  	message        string
   152  	seriesLabels   []cortexpb.LabelAdapter
   153  	exemplarLabels []cortexpb.LabelAdapter
   154  	timestamp      int64
   155  }
   156  
   157  func (e *exemplarValidationError) Error() string {
   158  	return fmt.Sprintf(e.message, e.timestamp, cortexpb.FromLabelAdaptersToLabels(e.seriesLabels).String(), cortexpb.FromLabelAdaptersToLabels(e.exemplarLabels).String())
   159  }
   160  
   161  func newExemplarEmtpyLabelsError(seriesLabels []cortexpb.LabelAdapter, exemplarLabels []cortexpb.LabelAdapter, timestamp int64) ValidationError {
   162  	return &exemplarValidationError{
   163  		message:        "exemplar missing labels, timestamp: %d series: %s labels: %s",
   164  		seriesLabels:   seriesLabels,
   165  		exemplarLabels: exemplarLabels,
   166  		timestamp:      timestamp,
   167  	}
   168  }
   169  
   170  func newExemplarMissingTimestampError(seriesLabels []cortexpb.LabelAdapter, exemplarLabels []cortexpb.LabelAdapter, timestamp int64) ValidationError {
   171  	return &exemplarValidationError{
   172  		message:        "exemplar missing timestamp, timestamp: %d series: %s labels: %s",
   173  		seriesLabels:   seriesLabels,
   174  		exemplarLabels: exemplarLabels,
   175  		timestamp:      timestamp,
   176  	}
   177  }
   178  
   179  var labelLenMsg = "exemplar combined labelset exceeds " + strconv.Itoa(ExemplarMaxLabelSetLength) + " characters, timestamp: %d series: %s labels: %s"
   180  
   181  func newExemplarLabelLengthError(seriesLabels []cortexpb.LabelAdapter, exemplarLabels []cortexpb.LabelAdapter, timestamp int64) ValidationError {
   182  	return &exemplarValidationError{
   183  		message:        labelLenMsg,
   184  		seriesLabels:   seriesLabels,
   185  		exemplarLabels: exemplarLabels,
   186  		timestamp:      timestamp,
   187  	}
   188  }
   189  
   190  // formatLabelSet formats label adapters as a metric name with labels, while preserving
   191  // label order, and keeping duplicates. If there are multiple "__name__" labels, only
   192  // first one is used as metric name, other ones will be included as regular labels.
   193  func formatLabelSet(ls []cortexpb.LabelAdapter) string {
   194  	metricName, hasMetricName := "", false
   195  
   196  	labelStrings := make([]string, 0, len(ls))
   197  	for _, l := range ls {
   198  		if l.Name == model.MetricNameLabel && !hasMetricName && l.Value != "" {
   199  			metricName = l.Value
   200  			hasMetricName = true
   201  		} else {
   202  			labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", l.Name, l.Value))
   203  		}
   204  	}
   205  
   206  	if len(labelStrings) == 0 {
   207  		if hasMetricName {
   208  			return metricName
   209  		}
   210  		return "{}"
   211  	}
   212  
   213  	return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", "))
   214  }