@@ -18,7 +18,7 @@ import (
18
18
19
19
// ingestLimitsFrontendClient is used for tests.
20
20
type ingestLimitsFrontendClient interface {
21
- exceedsLimits (context.Context , * proto.ExceedsLimitsRequest ) (* proto.ExceedsLimitsResponse , error )
21
+ ExceedsLimits (context.Context , * proto.ExceedsLimitsRequest ) (* proto.ExceedsLimitsResponse , error )
22
22
}
23
23
24
24
// ingestLimitsFrontendRingClient uses the ring to query ingest-limits frontends.
@@ -35,7 +35,7 @@ func newIngestLimitsFrontendRingClient(ring ring.ReadRing, pool *ring_client.Poo
35
35
}
36
36
37
37
// Implements the ingestLimitsFrontendClient interface.
38
- func (c * ingestLimitsFrontendRingClient ) exceedsLimits (ctx context.Context , req * proto.ExceedsLimitsRequest ) (* proto.ExceedsLimitsResponse , error ) {
38
+ func (c * ingestLimitsFrontendRingClient ) ExceedsLimits (ctx context.Context , req * proto.ExceedsLimitsRequest ) (* proto.ExceedsLimitsResponse , error ) {
39
39
// We use an FNV-1 of all stream hashes in the request to load balance requests
40
40
// to limits-frontends instances.
41
41
h := fnv .New32 ()
@@ -85,57 +85,65 @@ func newIngestLimits(client ingestLimitsFrontendClient, r prometheus.Registerer)
85
85
return & ingestLimits {
86
86
client : client ,
87
87
limitsFailures : promauto .With (r ).NewCounter (prometheus.CounterOpts {
88
- Name : "loki_distributor_ingest_limits_failures_total " ,
89
- Help : "The total number of failures checking ingest limits ." ,
88
+ Name : "loki_distributor_ingest_limits_requests_failed_total " ,
89
+ Help : "The total number of requests that failed ." ,
90
90
}),
91
91
}
92
92
}
93
93
94
- // enforceLimits returns a slice of streams that are within the per-tenant
95
- // limits, and in the case where one or more streams exceed per-tenant
96
- // limits, the reasons those streams were not included in the result.
97
- // An error is returned if per-tenant limits could not be enforced .
98
- func (l * ingestLimits ) enforceLimits (ctx context.Context , tenant string , streams []KeyedStream ) ([]KeyedStream , map [ uint64 ][] string , error ) {
99
- exceedsLimits , reasons , err := l .exceedsLimits (ctx , tenant , streams )
100
- if ! exceedsLimits || err != nil {
101
- return streams , nil , err
94
+ // EnforceLimits checks all streams against the per-tenant limits and returns
95
+ // a slice containing the streams that are accepted (within the per-tenant
96
+ // limits). Any streams that could not have their limits checked are also
97
+ // accepted .
98
+ func (l * ingestLimits ) EnforceLimits (ctx context.Context , tenant string , streams []KeyedStream ) ([]KeyedStream , error ) {
99
+ results , err := l .ExceedsLimits (ctx , tenant , streams )
100
+ if err != nil {
101
+ return streams , err
102
102
}
103
103
// We can do this without allocation if needed, but doing so will modify
104
104
// the original backing array. See "Filtering without allocation" from
105
105
// https://go.dev/wiki/SliceTricks.
106
- withinLimits := make ([]KeyedStream , 0 , len (streams ))
106
+ accepted := make ([]KeyedStream , 0 , len (streams ))
107
107
for _ , s := range streams {
108
- if _ , ok := reasons [s .HashKeyNoShard ]; ! ok {
109
- withinLimits = append (withinLimits , s )
108
+ // Check each stream to see if it failed.
109
+ // TODO(grobinson): We have an O(N*M) loop here. Need to benchmark if
110
+ // its faster to do this or if we should create a map instead.
111
+ var (
112
+ found bool
113
+ reason uint32
114
+ )
115
+ for _ , res := range results {
116
+ if res .StreamHash == s .HashKeyNoShard {
117
+ found = true
118
+ reason = res .Reason
119
+ break
120
+ }
121
+ }
122
+ if ! found || reason == uint32 (limits .ReasonFailed ) {
123
+ accepted = append (accepted , s )
110
124
}
111
125
}
112
- return withinLimits , reasons , nil
126
+ return accepted , nil
113
127
}
114
128
115
- // ExceedsLimits returns true if one or more streams exceeds per-tenant limits,
116
- // and false if no streams exceed per-tenant limits. In the case where one or
117
- // more streams exceeds per-tenant limits, it returns the reasons for each stream.
118
- // An error is returned if per-tenant limits could not be checked.
119
- func (l * ingestLimits ) exceedsLimits (ctx context.Context , tenant string , streams []KeyedStream ) (bool , map [uint64 ][]string , error ) {
129
+ // ExceedsLimits checks all streams against the per-tenant limits. It returns
130
+ // an error if the client failed to send the request or receive a response
131
+ // from the server. Any streams that could not have their limits checked
132
+ // and returned in the results with the reason "ReasonFailed".
133
+ func (l * ingestLimits ) ExceedsLimits (
134
+ ctx context.Context ,
135
+ tenant string ,
136
+ streams []KeyedStream ,
137
+ ) ([]* proto.ExceedsLimitsResult , error ) {
120
138
req , err := newExceedsLimitsRequest (tenant , streams )
121
139
if err != nil {
122
- return false , nil , err
140
+ return nil , err
123
141
}
124
- resp , err := l .client .exceedsLimits (ctx , req )
142
+ resp , err := l .client .ExceedsLimits (ctx , req )
125
143
if err != nil {
126
- return false , nil , err
127
- }
128
- if len (resp .Results ) == 0 {
129
- return false , nil , nil
130
- }
131
- reasonsForHashes := make (map [uint64 ][]string )
132
- for _ , result := range resp .Results {
133
- reasons := reasonsForHashes [result .StreamHash ]
134
- humanized := limits .Reason (result .Reason ).String ()
135
- reasons = append (reasons , humanized )
136
- reasonsForHashes [result .StreamHash ] = reasons
144
+ return nil , err
137
145
}
138
- return true , reasonsForHashes , nil
146
+ return resp . Results , nil
139
147
}
140
148
141
149
func newExceedsLimitsRequest (tenant string , streams []KeyedStream ) (* proto.ExceedsLimitsRequest , error ) {
@@ -156,10 +164,3 @@ func newExceedsLimitsRequest(tenant string, streams []KeyedStream) (*proto.Excee
156
164
Streams : streamMetadata ,
157
165
}, nil
158
166
}
159
-
160
- func firstReasonForHashes (reasonsForHashes map [uint64 ][]string ) string {
161
- for _ , reasons := range reasonsForHashes {
162
- return reasons [0 ]
163
- }
164
- return "unknown reason"
165
- }
0 commit comments