Skip to content

Commit

Permalink
Make MessageWithLimitConfig accept multiple flags
Browse files Browse the repository at this point in the history
  • Loading branch information
zenador committed Jun 8, 2022
1 parent eb812fd commit ad505db
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 51 deletions.
4 changes: 2 additions & 2 deletions pkg/distributor/distributor.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ var (
errInvalidTenantShardSize = errors.New("invalid tenant shard size, the value must be greater or equal to zero")

// Distributor instance limits errors.
errMaxInflightRequestsReached = errors.New(globalerror.DistributorMaxInflightPushRequests.MessageWithLimitConfig(maxInflightPushRequestsFlag, "the write request has been rejected because the distributor exceeded the allowed number of inflight push requests"))
errMaxIngestionRateReached = errors.New(globalerror.DistributorMaxIngestionRate.MessageWithLimitConfig(maxIngestionRateFlag, "the write request has been rejected because the distributor exceeded the ingestion rate limit"))
errMaxInflightRequestsReached = errors.New(globalerror.DistributorMaxInflightPushRequests.MessageWithLimitConfig("the write request has been rejected because the distributor exceeded the allowed number of inflight push requests", maxInflightPushRequestsFlag))
errMaxIngestionRateReached = errors.New(globalerror.DistributorMaxIngestionRate.MessageWithLimitConfig("the write request has been rejected because the distributor exceeded the ingestion rate limit", maxIngestionRateFlag))
)

const (
Expand Down
4 changes: 2 additions & 2 deletions pkg/distributor/ha_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,8 @@ type tooManyClustersError struct {

func (e tooManyClustersError) Error() string {
return globalerror.TooManyHAClusters.MessageWithLimitConfig(
validation.HATrackerMaxClustersFlag,
fmt.Sprintf("the write request has been rejected because the maximum number of high-availability (HA) clusters has been reached for this tenant (limit: %d)", e.limit))
fmt.Sprintf("the write request has been rejected because the maximum number of high-availability (HA) clusters has been reached for this tenant (limit: %d)", e.limit),
validation.HATrackerMaxClustersFlag)
}

// Needed for errors.Is to work properly.
Expand Down
8 changes: 4 additions & 4 deletions pkg/ingester/instance_limits.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ const (

var (
// We don't include values in the message to avoid leaking Mimir cluster configuration to users.
errMaxIngestionRateReached = errors.New(globalerror.IngesterMaxIngestionRate.MessageWithLimitConfig(maxIngestionRateFlag, "the write request has been rejected because the ingester exceeded the samples ingestion rate limit"))
errMaxTenantsReached = errors.New(globalerror.IngesterMaxTenants.MessageWithLimitConfig(maxInMemoryTenantsFlag, "the write request has been rejected because the ingester exceeded the allowed number of tenants"))
errMaxInMemorySeriesReached = errors.New(globalerror.IngesterMaxInMemorySeries.MessageWithLimitConfig(maxInMemorySeriesFlag, "the write request has been rejected because the ingester exceeded the allowed number of in-memory series"))
errMaxInflightRequestsReached = errors.New(globalerror.IngesterMaxInflightPushRequests.MessageWithLimitConfig(maxInflightPushRequestsFlag, "the write request has been rejected because the ingester exceeded the allowed number of inflight push requests"))
errMaxIngestionRateReached = errors.New(globalerror.IngesterMaxIngestionRate.MessageWithLimitConfig("the write request has been rejected because the ingester exceeded the samples ingestion rate limit", maxIngestionRateFlag))
errMaxTenantsReached = errors.New(globalerror.IngesterMaxTenants.MessageWithLimitConfig("the write request has been rejected because the ingester exceeded the allowed number of tenants", maxInMemoryTenantsFlag))
errMaxInMemorySeriesReached = errors.New(globalerror.IngesterMaxInMemorySeries.MessageWithLimitConfig("the write request has been rejected because the ingester exceeded the allowed number of in-memory series", maxInMemorySeriesFlag))
errMaxInflightRequestsReached = errors.New(globalerror.IngesterMaxInflightPushRequests.MessageWithLimitConfig("the write request has been rejected because the ingester exceeded the allowed number of inflight push requests", maxInflightPushRequestsFlag))
)

// InstanceLimits describes limits used by ingester. Reaching any of these will result in Push method to return
Expand Down
8 changes: 4 additions & 4 deletions pkg/ingester/limiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,35 +117,35 @@ func (l *Limiter) formatMaxSeriesPerUserError(userID string) error {
globalLimit := l.limits.MaxGlobalSeriesPerUser(userID)

return errors.New(globalerror.MaxSeriesPerUser.MessageWithLimitConfig(
validation.MaxSeriesPerUserFlag,
fmt.Sprintf("per-user series limit of %d exceeded", globalLimit),
validation.MaxSeriesPerUserFlag,
))
}

func (l *Limiter) formatMaxSeriesPerMetricError(userID string) error {
globalLimit := l.limits.MaxGlobalSeriesPerMetric(userID)

return errors.New(globalerror.MaxSeriesPerMetric.MessageWithLimitConfig(
validation.MaxSeriesPerMetricFlag,
fmt.Sprintf("per-metric series limit of %d exceeded", globalLimit),
validation.MaxSeriesPerMetricFlag,
))
}

func (l *Limiter) formatMaxMetadataPerUserError(userID string) error {
globalLimit := l.limits.MaxGlobalMetricsWithMetadataPerUser(userID)

return errors.New(globalerror.MaxMetadataPerUser.MessageWithLimitConfig(
validation.MaxMetadataPerUserFlag,
fmt.Sprintf("per-user metric metadata limit of %d exceeded", globalLimit),
validation.MaxMetadataPerUserFlag,
))
}

func (l *Limiter) formatMaxMetadataPerMetricError(userID string) error {
globalLimit := l.limits.MaxGlobalMetadataPerMetric(userID)

return errors.New(globalerror.MaxMetadataPerMetric.MessageWithLimitConfig(
validation.MaxMetadataPerMetricFlag,
fmt.Sprintf("per-metric metadata limit of %d exceeded", globalLimit),
validation.MaxMetadataPerMetricFlag,
))
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/querier/blocks_store_queryable.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ const (

var (
maxChunksPerQueryLimitMsgFormat = globalerror.MaxChunksPerQuery.MessageWithLimitConfig(
validation.MaxChunksPerQueryFlag,
"the query exceeded the maximum number of chunks fetched from store-gateways when querying '%s' (limit: %d)",
validation.MaxChunksPerQueryFlag,
)
)

Expand Down
10 changes: 3 additions & 7 deletions pkg/util/globalerror/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,9 @@ func (id ID) Message(msg string) string {
return fmt.Sprintf("%s (%s%s)", msg, errPrefix, id)
}

// MessageWithLimitConfig return the provided msg, appending the error id and a suggestion on
// which configuration flag to use to change the limit.
func (id ID) MessageWithLimitConfig(flag, msg string) string {
return fmt.Sprintf("%s (%s%s). You can adjust the related per-tenant limit by configuring -%s, or by contacting your service administrator.", msg, errPrefix, id, flag)
}

func (id ID) MessageWithLimitConfigs(msg, flag string, addFlags ...string) string {
// MessageWithLimitConfig returns the provided msg, appending the error id and a suggestion on
// which configuration flag(s) to use to change the limit.
func (id ID) MessageWithLimitConfig(msg, flag string, addFlags ...string) string {
var sb strings.Builder
sb.WriteString("-")
sb.WriteString(flag)
Expand Down
13 changes: 3 additions & 10 deletions pkg/util/globalerror/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,21 @@ func TestID_Message(t *testing.T) {
}

func TestID_MessageWithLimitConfig(t *testing.T) {
assert.Equal(
t,
"an error (err-mimir-missing-metric-name). You can adjust the related per-tenant limit by configuring -my-flag, or by contacting your service administrator.",
MissingMetricName.MessageWithLimitConfig("my-flag", "an error"))
}

func TestID_MessageWithLimitConfigs(t *testing.T) {
for _, tc := range []struct {
actual string
expected string
}{
{
actual: "an error (err-mimir-missing-metric-name). You can adjust the related per-tenant limit by configuring -my-flag1, or by contacting your service administrator.",
expected: MissingMetricName.MessageWithLimitConfigs("an error", "my-flag1"),
expected: MissingMetricName.MessageWithLimitConfig("an error", "my-flag1"),
},
{
actual: "an error (err-mimir-missing-metric-name). You can adjust the related per-tenant limits by configuring -my-flag1 and -my-flag2, or by contacting your service administrator.",
expected: MissingMetricName.MessageWithLimitConfigs("an error", "my-flag1", "my-flag2"),
expected: MissingMetricName.MessageWithLimitConfig("an error", "my-flag1", "my-flag2"),
},
{
actual: "an error (err-mimir-missing-metric-name). You can adjust the related per-tenant limits by configuring -my-flag1, -my-flag2 and -my-flag3, or by contacting your service administrator.",
expected: MissingMetricName.MessageWithLimitConfigs("an error", "my-flag1", "my-flag2", "my-flag3"),
expected: MissingMetricName.MessageWithLimitConfig("an error", "my-flag1", "my-flag2", "my-flag3"),
},
} {
assert.Equal(t, tc.actual, tc.expected)
Expand Down
6 changes: 3 additions & 3 deletions pkg/util/limiter/query_limiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ type queryLimiterCtxKey struct{}
var (
ctxKey = &queryLimiterCtxKey{}
MaxSeriesHitMsgFormat = globalerror.MaxSeriesPerQuery.MessageWithLimitConfig(
validation.MaxSeriesPerQueryFlag,
"the query exceeded the maximum number of series (limit: %d series)",
validation.MaxSeriesPerQueryFlag,
)
MaxChunkBytesHitMsgFormat = globalerror.MaxChunkBytesPerQuery.MessageWithLimitConfig(
validation.MaxChunkBytesPerQueryFlag,
"the query exceeded the aggregated chunks size limit (limit: %d bytes)",
validation.MaxChunkBytesPerQueryFlag,
)
MaxChunksPerQueryLimitMsgFormat = globalerror.MaxChunksPerQuery.MessageWithLimitConfig(
validation.MaxChunksPerQueryFlag,
"the query exceeded the maximum number of chunks (limit: %d chunks)",
validation.MaxChunksPerQueryFlag,
)
)

Expand Down
36 changes: 18 additions & 18 deletions pkg/util/validation/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ func (e genericValidationError) Error() string {
}

var labelNameTooLongMsgFormat = globalerror.SeriesLabelNameTooLong.MessageWithLimitConfig(
maxLabelNameLengthFlag,
"received a series whose label name length exceeds the limit, label: '%.200s' series: '%.200s'")
"received a series whose label name length exceeds the limit, label: '%.200s' series: '%.200s'",
maxLabelNameLengthFlag)

func newLabelNameTooLongError(series []mimirpb.LabelAdapter, labelName string) ValidationError {
return genericValidationError{
Expand All @@ -54,8 +54,8 @@ type labelValueTooLongError struct {

func (e labelValueTooLongError) Error() string {
return globalerror.SeriesLabelValueTooLong.MessageWithLimitConfig(
maxLabelValueLengthFlag,
fmt.Sprintf("received a series whose label value length exceeds the limit, value: '%.200s' (truncated) series: '%.200s'", e.labelValue, formatLabelSet(e.series)))
fmt.Sprintf("received a series whose label value length exceeds the limit, value: '%.200s' (truncated) series: '%.200s'", e.labelValue, formatLabelSet(e.series)),
maxLabelValueLengthFlag)
}

func newLabelValueTooLongError(series []mimirpb.LabelAdapter, labelValue string) ValidationError {
Expand Down Expand Up @@ -112,8 +112,8 @@ func newTooManyLabelsError(series []mimirpb.LabelAdapter, limit int) ValidationE

func (e tooManyLabelsError) Error() string {
return globalerror.MaxLabelNamesPerSeries.MessageWithLimitConfig(
maxLabelNamesPerSeriesFlag,
fmt.Sprintf("received a series whose number of labels exceeds the limit (actual: %d, limit: %d) series: '%.200s'", len(e.series), e.limit, mimirpb.FromLabelAdaptersToMetric(e.series).String()))
fmt.Sprintf("received a series whose number of labels exceeds the limit (actual: %d, limit: %d) series: '%.200s'", len(e.series), e.limit, mimirpb.FromLabelAdaptersToMetric(e.series).String()),
maxLabelNamesPerSeriesFlag)
}

type noMetricNameError struct{}
Expand Down Expand Up @@ -152,8 +152,8 @@ func (e sampleValidationError) Error() string {
}

var sampleTimestampTooNewMsgFormat = globalerror.SampleTooFarInFuture.MessageWithLimitConfig(
creationGracePeriodFlag,
"received a sample whose timestamp is too far in the future, timestamp: %d series: '%.200s'")
"received a sample whose timestamp is too far in the future, timestamp: %d series: '%.200s'",
creationGracePeriodFlag)

func newSampleTimestampTooNewError(metricName string, timestamp int64) ValidationError {
return sampleValidationError{
Expand Down Expand Up @@ -233,9 +233,9 @@ func (e metadataValidationError) Error() string {
}

var metadataMetricNameTooLongMsgFormat = globalerror.MetricMetadataMetricNameTooLong.MessageWithLimitConfig(
maxMetadataLengthFlag,
// When formatting this error the "cause" will always be an empty string.
"received a metric metadata whose metric name length exceeds the limit, metric name: '%.200[2]s'")
"received a metric metadata whose metric name length exceeds the limit, metric name: '%.200[2]s'",
maxMetadataLengthFlag)

func newMetadataMetricNameTooLongError(metadata *mimirpb.MetricMetadata) ValidationError {
return metadataValidationError{
Expand All @@ -246,8 +246,8 @@ func newMetadataMetricNameTooLongError(metadata *mimirpb.MetricMetadata) Validat
}

var metadataHelpTooLongMsgFormat = globalerror.MetricMetadataHelpTooLong.MessageWithLimitConfig(
maxMetadataLengthFlag,
"received a metric metadata whose help description length exceeds the limit, help: '%.200s' metric name: '%.200s'")
"received a metric metadata whose help description length exceeds the limit, help: '%.200s' metric name: '%.200s'",
maxMetadataLengthFlag)

func newMetadataHelpTooLongError(metadata *mimirpb.MetricMetadata) ValidationError {
return metadataValidationError{
Expand All @@ -258,8 +258,8 @@ func newMetadataHelpTooLongError(metadata *mimirpb.MetricMetadata) ValidationErr
}

var metadataUnitTooLongMsgFormat = globalerror.MetricMetadataUnitTooLong.MessageWithLimitConfig(
maxMetadataLengthFlag,
"received a metric metadata whose unit name length exceeds the limit, unit: '%.200s' metric name: '%.200s'")
"received a metric metadata whose unit name length exceeds the limit, unit: '%.200s' metric name: '%.200s'",
maxMetadataLengthFlag)

func newMetadataUnitTooLongError(metadata *mimirpb.MetricMetadata) ValidationError {
return metadataValidationError{
Expand All @@ -271,18 +271,18 @@ func newMetadataUnitTooLongError(metadata *mimirpb.MetricMetadata) ValidationErr

func NewMaxQueryLengthError(actualQueryLen, maxQueryLength time.Duration) LimitError {
return LimitError(globalerror.MaxQueryLength.MessageWithLimitConfig(
maxQueryLengthFlag,
fmt.Sprintf("the query time range exceeds the limit (query length: %s, limit: %s)", actualQueryLen, maxQueryLength)))
fmt.Sprintf("the query time range exceeds the limit (query length: %s, limit: %s)", actualQueryLen, maxQueryLength),
maxQueryLengthFlag))
}

func NewRequestRateLimitedError(limit float64, burst int) LimitError {
return LimitError(globalerror.RequestRateLimited.MessageWithLimitConfigs(
return LimitError(globalerror.RequestRateLimited.MessageWithLimitConfig(
fmt.Sprintf("the request has been rejected because the tenant exceeded the request rate limit, set to %v req/s with a maximum allowed burst of %d", limit, burst),
requestRateFlag, requestBurstSizeFlag))
}

func NewIngestionRateLimitedError(limit float64, burst, numSamples, numExemplars, numMetadata int) LimitError {
return LimitError(globalerror.IngestionRateLimited.MessageWithLimitConfigs(
return LimitError(globalerror.IngestionRateLimited.MessageWithLimitConfig(
fmt.Sprintf("the request has been rejected because the tenant exceeded the ingestion rate limit, set to %v items/s with a maximum allowed burst of %d, while adding %d samples, %d exemplars and %d metadata", limit, burst, numSamples, numExemplars, numMetadata),
ingestionRateFlag, ingestionBurstSizeFlag))
}
Expand Down

0 comments on commit ad505db

Please sign in to comment.