Skip to content

Commit f414266

Browse files
author
Ganesh Vernekar
committed
Fix remaining comments
Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
1 parent 7ae2d0b commit f414266

File tree

8 files changed

+117
-20
lines changed

8 files changed

+117
-20
lines changed

docs/configuration/config-file-reference.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ ha_tracker:
486486
[mirror_timeout: <duration> | default = 2s]
487487
488488
# remote_write API max receive message size (bytes).
489-
# CLI flag: -distributor.max-recv-msg-size
489+
# CLI flag: -distributor.max-recv-body-size
490490
[max_recv_msg_size: <int> | default = 104857600]
491491
492492
# Timeout for downstream ingesters.
@@ -1542,6 +1542,10 @@ The `alertmanager_config` configures the Cortex alertmanager.
15421542
# CLI flag: -alertmanager.configs.poll-interval
15431543
[poll_interval: <duration> | default = 15s]
15441544
1545+
# Max receive http body size (bytes).
1546+
# CLI flag: -alertmanager.max-recv-msg-size
1547+
[max_recv_msg_size: <int> | default = 16777216]
1548+
15451549
# Deprecated. Use -alertmanager.cluster.listen-address instead.
15461550
# CLI flag: -cluster.listen-address
15471551
[cluster_bind_address: <string> | default = "0.0.0.0:9094"]

pkg/alertmanager/distributor.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ func (d *Distributor) doWrite(userID string, w http.ResponseWriter, r *http.Requ
9696
if r.Body != nil {
9797
body, err = ioutil.ReadAll(r.Body)
9898
if err != nil {
99+
if err.Error() == "http: request body too large\n" {
100+
http.Error(w, "Request body too large", http.StatusBadRequest)
101+
}
99102
level.Error(logger).Log("msg", "failed to read the request body during write", "err", err)
100103
w.WriteHeader(http.StatusInternalServerError)
101104
return
@@ -110,9 +113,8 @@ func (d *Distributor) doWrite(userID string, w http.ResponseWriter, r *http.Requ
110113
localCtx, cancel := context.WithTimeout(context.Background(), d.cfg.AlertmanagerClient.RemoteTimeout)
111114
defer cancel()
112115
localCtx = user.InjectOrgID(localCtx, userID)
113-
if sp := opentracing.SpanFromContext(r.Context()); sp != nil {
114-
localCtx = opentracing.ContextWithSpan(localCtx, sp)
115-
}
116+
sp, localCtx := opentracing.StartSpanFromContext(localCtx, "DistributeRequest.doWrite")
117+
defer sp.Finish()
116118

117119
resp, err := d.doRequest(localCtx, am, &httpgrpc.HTTPRequest{
118120
Method: r.Method,
@@ -141,8 +143,12 @@ func (d *Distributor) doWrite(userID string, w http.ResponseWriter, r *http.Requ
141143
respondFromError(err, w, logger)
142144
}
143145

144-
if firstSuccessfulResponse != nil {
145-
respondFromHTTPGRPCResponse(w, firstSuccessfulResponse)
146+
respMtx.Lock() // Another request might be ongoing after quorum.
147+
resp := firstSuccessfulResponse
148+
respMtx.Unlock()
149+
150+
if resp != nil {
151+
respondFromHTTPGRPCResponse(w, resp)
146152
} else {
147153
// This should not happen.
148154
level.Error(logger).Log("msg", "distributor did not receive response from alertmanager though no errors")
@@ -168,6 +174,9 @@ func (d *Distributor) doRead(userID string, w http.ResponseWriter, r *http.Reque
168174

169175
ctx, cancel := context.WithTimeout(r.Context(), d.cfg.AlertmanagerClient.RemoteTimeout)
170176
defer cancel()
177+
178+
sp, ctx := opentracing.StartSpanFromContext(ctx, "DistributeRequest.doRead")
179+
defer sp.Finish()
171180
// Until we have a mechanism to combine the results from multiple alertmanagers,
172181
// we forward the request to only only of the alertmanagers.
173182
amDesc := replicationSet.Ingesters[rand.Intn(len(replicationSet.Ingesters))]
@@ -197,7 +206,7 @@ func respondFromHTTPGRPCResponse(w http.ResponseWriter, httpResp *httpgrpc.HTTPR
197206
}
198207
}
199208
w.WriteHeader(int(httpResp.Code))
200-
w.Write(httpResp.Body)
209+
w.Write(httpResp.Body) //nolint
201210
}
202211

203212
func (d *Distributor) doRequest(ctx context.Context, am ring.InstanceDesc, req *httpgrpc.HTTPRequest) (*httpgrpc.HTTPResponse, error) {

pkg/alertmanager/multitenant.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"flag"
66
"fmt"
7-
"github.com/weaveworks/common/httpgrpc"
87
"hash/fnv"
98
"html/template"
109
"io/ioutil"
@@ -22,6 +21,7 @@ import (
2221
amconfig "github.com/prometheus/alertmanager/config"
2322
"github.com/prometheus/client_golang/prometheus"
2423
"github.com/prometheus/client_golang/prometheus/promauto"
24+
"github.com/weaveworks/common/httpgrpc"
2525
"github.com/weaveworks/common/httpgrpc/server"
2626

2727
"github.com/cortexproject/cortex/pkg/alertmanager/alerts"
@@ -92,10 +92,11 @@ func init() {
9292

9393
// MultitenantAlertmanagerConfig is the configuration for a multitenant Alertmanager.
9494
type MultitenantAlertmanagerConfig struct {
95-
DataDir string `yaml:"data_dir"`
96-
Retention time.Duration `yaml:"retention"`
97-
ExternalURL flagext.URLValue `yaml:"external_url"`
98-
PollInterval time.Duration `yaml:"poll_interval"`
95+
DataDir string `yaml:"data_dir"`
96+
Retention time.Duration `yaml:"retention"`
97+
ExternalURL flagext.URLValue `yaml:"external_url"`
98+
PollInterval time.Duration `yaml:"poll_interval"`
99+
MaxRecvMsgSize int64 `yaml:"max_recv_msg_size"`
99100

100101
DeprecatedClusterBindAddr string `yaml:"cluster_bind_address"`
101102
DeprecatedClusterAdvertiseAddr string `yaml:"cluster_advertise_address"`
@@ -136,6 +137,7 @@ const (
136137
func (cfg *MultitenantAlertmanagerConfig) RegisterFlags(f *flag.FlagSet) {
137138
f.StringVar(&cfg.DataDir, "alertmanager.storage.path", "data/", "Base path for data storage.")
138139
f.DurationVar(&cfg.Retention, "alertmanager.storage.retention", 5*24*time.Hour, "How long to keep data for.")
140+
f.Int64Var(&cfg.MaxRecvMsgSize, "alertmanager.max-recv-msg-size", 16<<20, "Max receive http body size (bytes).")
139141

140142
f.Var(&cfg.ExternalURL, "alertmanager.web.external-url", "The URL under which Alertmanager is externally reachable (for example, if Alertmanager is served via a reverse proxy). Used for generating relative and absolute links back to Alertmanager itself. If the URL has a path portion, it will be used to prefix all HTTP endpoints served by Alertmanager. If omitted, relevant URL components will be derived automatically.")
141143

pkg/api/api.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/cortexproject/cortex/pkg/scheduler/schedulerpb"
3434
"github.com/cortexproject/cortex/pkg/storegateway"
3535
"github.com/cortexproject/cortex/pkg/storegateway/storegatewaypb"
36+
"github.com/cortexproject/cortex/pkg/util"
3637
"github.com/cortexproject/cortex/pkg/util/push"
3738
)
3839

@@ -158,7 +159,7 @@ func (a *API) RegisterRoutesWithPrefix(prefix string, handler http.Handler, auth
158159

159160
// RegisterAlertmanager registers endpoints associated with the alertmanager. It will only
160161
// serve endpoints using the legacy http-prefix if it is not run as a single binary.
161-
func (a *API) RegisterAlertmanager(am *alertmanager.MultitenantAlertmanager, target, apiEnabled bool) {
162+
func (a *API) RegisterAlertmanager(am *alertmanager.MultitenantAlertmanager, amCfg alertmanager.MultitenantAlertmanagerConfig, target, apiEnabled bool) {
162163
alertmanagerpb.RegisterAlertmanagerServer(a.server.GRPC, am)
163164

164165
a.indexPage.AddLink(SectionAdminEndpoints, "/multitenant_alertmanager/status", "Alertmanager Status")
@@ -168,21 +169,21 @@ func (a *API) RegisterAlertmanager(am *alertmanager.MultitenantAlertmanager, tar
168169
a.RegisterRoute("/multitenant_alertmanager/ring", http.HandlerFunc(am.RingHandler), false, "GET", "POST")
169170

170171
// UI components lead to a large number of routes to support, utilize a path prefix instead
171-
a.RegisterRoutesWithPrefix(a.cfg.AlertmanagerHTTPPrefix, am, true)
172+
a.RegisterRoutesWithPrefix(a.cfg.AlertmanagerHTTPPrefix, util.NewMaxBytesHandler(am, amCfg.MaxRecvMsgSize), true)
172173
level.Debug(a.logger).Log("msg", "api: registering alertmanager", "path_prefix", a.cfg.AlertmanagerHTTPPrefix)
173174

174175
// If the target is Alertmanager, enable the legacy behaviour. Otherwise only enable
175176
// the component routed API.
176177
if target {
177178
a.RegisterRoute("/status", am.GetStatusHandler(), false, "GET")
178-
a.RegisterRoutesWithPrefix(a.cfg.LegacyHTTPPrefix, am, true)
179+
a.RegisterRoutesWithPrefix(a.cfg.LegacyHTTPPrefix, util.NewMaxBytesHandler(am, amCfg.MaxRecvMsgSize), true)
179180
}
180181

181182
// MultiTenant Alertmanager Experimental API routes
182183
if apiEnabled {
183-
a.RegisterRoute("/api/v1/alerts", http.HandlerFunc(am.GetUserConfig), true, "GET")
184-
a.RegisterRoute("/api/v1/alerts", http.HandlerFunc(am.SetUserConfig), true, "POST")
185-
a.RegisterRoute("/api/v1/alerts", http.HandlerFunc(am.DeleteUserConfig), true, "DELETE")
184+
a.RegisterRoute("/api/v1/alerts", util.NewMaxBytesHandler(http.HandlerFunc(am.GetUserConfig), amCfg.MaxRecvMsgSize), true, "GET")
185+
a.RegisterRoute("/api/v1/alerts", util.NewMaxBytesHandler(http.HandlerFunc(am.SetUserConfig), amCfg.MaxRecvMsgSize), true, "POST")
186+
a.RegisterRoute("/api/v1/alerts", util.NewMaxBytesHandler(http.HandlerFunc(am.DeleteUserConfig), amCfg.MaxRecvMsgSize), true, "DELETE")
186187
}
187188
}
188189

pkg/cortex/modules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ func (t *Cortex) initAlertManager() (serv services.Service, err error) {
679679
return
680680
}
681681

682-
t.API.RegisterAlertmanager(t.Alertmanager, t.Cfg.isModuleEnabled(AlertManager), t.Cfg.Alertmanager.EnableAPI)
682+
t.API.RegisterAlertmanager(t.Alertmanager, t.Cfg.Alertmanager, t.Cfg.isModuleEnabled(AlertManager), t.Cfg.Alertmanager.EnableAPI)
683683
return t.Alertmanager, nil
684684
}
685685

pkg/distributor/distributor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
180180
cfg.HATrackerConfig.RegisterFlags(f)
181181
cfg.DistributorRing.RegisterFlags(f)
182182

183-
f.IntVar(&cfg.MaxRecvMsgSize, "distributor.max-recv-msg-size", 100<<20, "remote_write API max receive message size (bytes).")
183+
f.IntVar(&cfg.MaxRecvMsgSize, "distributor.max-recv-body-size", 100<<20, "remote_write API max receive message size (bytes).")
184184
f.DurationVar(&cfg.RemoteTimeout, "distributor.remote-timeout", 2*time.Second, "Timeout for downstream ingesters.")
185185
f.DurationVar(&cfg.ExtraQueryDelay, "distributor.extra-query-delay", 0, "Time to wait before sending more than the minimum successful query requests.")
186186
f.BoolVar(&cfg.ShardByAllLabels, "distributor.shard-by-all-labels", false, "Distribute samples based on all labels, as opposed to solely by user and metric name.")

pkg/util/http.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,24 @@ func SerializeProtoResponse(w http.ResponseWriter, resp proto.Message, compressi
218218
}
219219
return nil
220220
}
221+
222+
type MaxBytesHandler struct {
223+
h http.Handler
224+
maxBytes int64
225+
}
226+
227+
// NewMaxBytesHandler returns a MaxBytesHandler.
228+
// If maxBytes<0, then the max bytes is not used and the passed handler is returned back.
229+
func NewMaxBytesHandler(h http.Handler, maxBytes int64) http.Handler {
230+
if maxBytes < 0 {
231+
return h
232+
}
233+
return &MaxBytesHandler{h: h, maxBytes: maxBytes}
234+
}
235+
236+
func (h *MaxBytesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
237+
r.Body = http.MaxBytesReader(w, r.Body, h.maxBytes)
238+
if h.h != nil {
239+
h.h.ServeHTTP(w, r)
240+
}
241+
}

pkg/util/http_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"bytes"
55
"context"
66
"html/template"
7+
"io/ioutil"
8+
"net/http"
79
"net/http/httptest"
810
"testing"
911

@@ -157,3 +159,61 @@ func (b bytesBuffered) Close() error {
157159
func (b bytesBuffered) BytesBuffer() *bytes.Buffer {
158160
return b.Buffer
159161
}
162+
163+
func TestMaxBytesHandler(t *testing.T) {
164+
cases := []struct {
165+
inpBody []byte
166+
maxSize int64
167+
expBody string
168+
expStatusCode int
169+
}{
170+
{
171+
inpBody: []byte{1, 2, 3, 4},
172+
maxSize: 4,
173+
expBody: "all is well",
174+
expStatusCode: http.StatusOK,
175+
}, {
176+
inpBody: []byte{1, 2, 3, 4},
177+
maxSize: 3,
178+
expBody: "http: request body too large\n",
179+
expStatusCode: http.StatusBadRequest,
180+
}, {
181+
inpBody: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
182+
maxSize: -1,
183+
expBody: "all is well",
184+
expStatusCode: http.StatusOK,
185+
}, {
186+
inpBody: []byte{1},
187+
maxSize: 0,
188+
expBody: "http: request body too large\n",
189+
expStatusCode: http.StatusBadRequest,
190+
},
191+
}
192+
for _, c := range cases {
193+
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1/all-is-well", bytes.NewReader(c.inpBody))
194+
assert.NoError(t, err)
195+
196+
h := util.NewMaxBytesHandler(&mockHandler{}, c.maxSize)
197+
w := httptest.NewRecorder()
198+
h.ServeHTTP(w, req)
199+
200+
assert.Equal(t, c.expStatusCode, w.Code)
201+
202+
b, err := ioutil.ReadAll(w.Body)
203+
assert.NoError(t, err)
204+
assert.Equal(t, c.expBody, string(b))
205+
}
206+
}
207+
208+
type mockHandler struct {
209+
http.Handler
210+
}
211+
212+
func (mockHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
213+
_, err := ioutil.ReadAll(req.Body)
214+
if err != nil {
215+
http.Error(w, err.Error(), http.StatusBadRequest)
216+
return
217+
}
218+
w.Write([]byte("all is well")) //nolint
219+
}

0 commit comments

Comments
 (0)