mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
all: consistently return text-based HTTP responses with charset=utf-8
This is a follow-up for https://github.com/VictoriaMetrics/VictoriaMetrics/pull/897
This commit is contained in:
parent
077f8cbe1c
commit
47a038401b
11 changed files with 40 additions and 38 deletions
|
@ -228,7 +228,7 @@ func requestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
errMsg := fmt.Sprintf("waiting for scrapes to init, left: %d", rdy)
|
errMsg := fmt.Sprintf("waiting for scrapes to init, left: %d", rdy)
|
||||||
http.Error(w, errMsg, http.StatusTooEarly)
|
http.Error(w, errMsg, http.StatusTooEarly)
|
||||||
} else {
|
} else {
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte("OK"))
|
w.Write([]byte("OK"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ func (s *VMStorage) Query(ctx context.Context, query string) ([]Metric, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||||
if s.basicAuthPass != "" {
|
if s.basicAuthPass != "" {
|
||||||
req.SetBasicAuth(s.basicAuthUser, s.basicAuthPass)
|
req.SetBasicAuth(s.basicAuthUser, s.basicAuthPass)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func (am *AlertManager) Send(ctx context.Context, alerts []Alert) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
if am.basicAuthPass != "" {
|
if am.basicAuthPass != "" {
|
||||||
req.SetBasicAuth(am.basicAuthUser, am.basicAuthPass)
|
req.SetBasicAuth(am.basicAuthUser, am.basicAuthPass)
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
httpserver.Errorf(w, r, "error in %q: %s", r.URL.Path, err)
|
httpserver.Errorf(w, r, "error in %q: %s", r.URL.Path, err)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
return true
|
return true
|
||||||
case "/api/v1/alerts":
|
case "/api/v1/alerts":
|
||||||
|
@ -49,7 +49,7 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
httpserver.Errorf(w, r, "error in %q: %s", r.URL.Path, err)
|
httpserver.Errorf(w, r, "error in %q: %s", r.URL.Path, err)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
return true
|
return true
|
||||||
case "/-/reload":
|
case "/-/reload":
|
||||||
|
@ -67,7 +67,7 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
httpserver.Errorf(w, r, "error in %q: %s", r.URL.Path, err)
|
httpserver.Errorf(w, r, "error in %q: %s", r.URL.Path, err)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,13 +155,13 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
return true
|
return true
|
||||||
case "/targets":
|
case "/targets":
|
||||||
promscrapeTargetsRequests.Inc()
|
promscrapeTargetsRequests.Inc()
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
showOriginalLabels, _ := strconv.ParseBool(r.FormValue("show_original_labels"))
|
showOriginalLabels, _ := strconv.ParseBool(r.FormValue("show_original_labels"))
|
||||||
promscrape.WriteHumanReadableTargetsStatus(w, showOriginalLabels)
|
promscrape.WriteHumanReadableTargetsStatus(w, showOriginalLabels)
|
||||||
return true
|
return true
|
||||||
case "/api/v1/targets":
|
case "/api/v1/targets":
|
||||||
promscrapeAPIV1TargetsRequests.Inc()
|
promscrapeAPIV1TargetsRequests.Inc()
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
state := r.FormValue("state")
|
state := r.FormValue("state")
|
||||||
promscrape.WriteAPIV1Targets(w, state)
|
promscrape.WriteAPIV1Targets(w, state)
|
||||||
return true
|
return true
|
||||||
|
@ -175,7 +175,7 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
errMsg := fmt.Sprintf("waiting for scrape config to init targets, configs left: %d", rdy)
|
errMsg := fmt.Sprintf("waiting for scrape config to init targets, configs left: %d", rdy)
|
||||||
http.Error(w, errMsg, http.StatusTooEarly)
|
http.Error(w, errMsg, http.StatusTooEarly)
|
||||||
} else {
|
} else {
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte("OK"))
|
w.Write([]byte("OK"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,9 +84,9 @@ func MetricsFindHandler(startTime time.Time, w http.ResponseWriter, r *http.Requ
|
||||||
}
|
}
|
||||||
paths = deduplicatePaths(paths, delimiter)
|
paths = deduplicatePaths(paths, delimiter)
|
||||||
sortPaths(paths, delimiter)
|
sortPaths(paths, delimiter)
|
||||||
contentType := "application/json"
|
contentType := "application/json; charset=utf-8"
|
||||||
if jsonp != "" {
|
if jsonp != "" {
|
||||||
contentType = "text/javascript"
|
contentType = "text/javascript; charset=utf-8"
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
|
@ -166,9 +166,9 @@ func MetricsExpandHandler(startTime time.Time, w http.ResponseWriter, r *http.Re
|
||||||
}
|
}
|
||||||
m[query] = paths
|
m[query] = paths
|
||||||
}
|
}
|
||||||
contentType := "application/json"
|
contentType := "application/json; charset=utf-8"
|
||||||
if jsonp != "" {
|
if jsonp != "" {
|
||||||
contentType = "text/javascript"
|
contentType = "text/javascript; charset=utf-8"
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
if groupByExpr {
|
if groupByExpr {
|
||||||
|
@ -215,9 +215,9 @@ func MetricsIndexHandler(startTime time.Time, w http.ResponseWriter, r *http.Req
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(`cannot obtain metric names: %w`, err)
|
return fmt.Errorf(`cannot obtain metric names: %w`, err)
|
||||||
}
|
}
|
||||||
contentType := "application/json"
|
contentType := "application/json; charset=utf-8"
|
||||||
if jsonp != "" {
|
if jsonp != "" {
|
||||||
contentType = "text/javascript"
|
contentType = "text/javascript; charset=utf-8"
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
|
|
|
@ -262,19 +262,19 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
case "/api/v1/rules":
|
case "/api/v1/rules":
|
||||||
// Return dumb placeholder
|
// Return dumb placeholder
|
||||||
rulesRequests.Inc()
|
rulesRequests.Inc()
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
fmt.Fprintf(w, "%s", `{"status":"success","data":{"groups":[]}}`)
|
fmt.Fprintf(w, "%s", `{"status":"success","data":{"groups":[]}}`)
|
||||||
return true
|
return true
|
||||||
case "/api/v1/alerts":
|
case "/api/v1/alerts":
|
||||||
// Return dumb placehloder
|
// Return dumb placehloder
|
||||||
alertsRequests.Inc()
|
alertsRequests.Inc()
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
fmt.Fprintf(w, "%s", `{"status":"success","data":{"alerts":[]}}`)
|
fmt.Fprintf(w, "%s", `{"status":"success","data":{"alerts":[]}}`)
|
||||||
return true
|
return true
|
||||||
case "/api/v1/metadata":
|
case "/api/v1/metadata":
|
||||||
// Return dumb placeholder
|
// Return dumb placeholder
|
||||||
metadataRequests.Inc()
|
metadataRequests.Inc()
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
fmt.Fprintf(w, "%s", `{"status":"success","data":{}}`)
|
fmt.Fprintf(w, "%s", `{"status":"success","data":{}}`)
|
||||||
return true
|
return true
|
||||||
case "/api/v1/admin/tsdb/delete_series":
|
case "/api/v1/admin/tsdb/delete_series":
|
||||||
|
@ -299,7 +299,7 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
func sendPrometheusError(w http.ResponseWriter, r *http.Request, err error) {
|
func sendPrometheusError(w http.ResponseWriter, r *http.Request, err error) {
|
||||||
logger.Warnf("error in %q: %s", r.RequestURI, err)
|
logger.Warnf("error in %q: %s", r.RequestURI, err)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
statusCode := http.StatusUnprocessableEntity
|
statusCode := http.StatusUnprocessableEntity
|
||||||
var esc *httpserver.ErrorWithStatusCode
|
var esc *httpserver.ErrorWithStatusCode
|
||||||
if errors.As(err, &esc) {
|
if errors.As(err, &esc) {
|
||||||
|
|
|
@ -88,7 +88,7 @@ func FederateHandler(startTime time.Time, w http.ResponseWriter, r *http.Request
|
||||||
return fmt.Errorf("cannot fetch data for %q: %w", sq, err)
|
return fmt.Errorf("cannot fetch data for %q: %w", sq, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
err = rss.RunParallel(func(rs *netstorage.Result, workerID uint) error {
|
err = rss.RunParallel(func(rs *netstorage.Result, workerID uint) error {
|
||||||
|
@ -151,7 +151,7 @@ func ExportCSVHandler(startTime time.Time, w http.ResponseWriter, r *http.Reques
|
||||||
MaxTimestamp: end,
|
MaxTimestamp: end,
|
||||||
TagFilterss: tagFilterss,
|
TagFilterss: tagFilterss,
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "text/csv")
|
w.Header().Set("Content-Type", "text/csv; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
|
|
||||||
|
@ -331,9 +331,9 @@ func exportHandler(w http.ResponseWriter, matches []string, start, end int64, fo
|
||||||
WriteExportJSONLine(bb, xb)
|
WriteExportJSONLine(bb, xb)
|
||||||
resultsCh <- bb
|
resultsCh <- bb
|
||||||
}
|
}
|
||||||
contentType := "application/stream+json"
|
contentType := "application/stream+json; charset=utf-8"
|
||||||
if format == "prometheus" {
|
if format == "prometheus" {
|
||||||
contentType = "text/plain"
|
contentType = "text/plain; charset=utf-8"
|
||||||
writeLineFunc = func(xb *exportBlock, resultsCh chan<- *quicktemplate.ByteBuffer) {
|
writeLineFunc = func(xb *exportBlock, resultsCh chan<- *quicktemplate.ByteBuffer) {
|
||||||
bb := quicktemplate.AcquireByteBuffer()
|
bb := quicktemplate.AcquireByteBuffer()
|
||||||
WriteExportPrometheusLine(bb, xb)
|
WriteExportPrometheusLine(bb, xb)
|
||||||
|
@ -561,7 +561,7 @@ func LabelValuesHandler(startTime time.Time, labelName string, w http.ResponseWr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
WriteLabelValuesResponse(bw, labelValues)
|
WriteLabelValuesResponse(bw, labelValues)
|
||||||
|
@ -639,7 +639,7 @@ func LabelsCountHandler(startTime time.Time, w http.ResponseWriter, r *http.Requ
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(`cannot obtain label entries: %w`, err)
|
return fmt.Errorf(`cannot obtain label entries: %w`, err)
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
WriteLabelsCountResponse(bw, labelEntries)
|
WriteLabelsCountResponse(bw, labelEntries)
|
||||||
|
@ -690,7 +690,7 @@ func TSDBStatusHandler(startTime time.Time, w http.ResponseWriter, r *http.Reque
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(`cannot obtain tsdb status for date=%d, topN=%d: %w`, date, topN, err)
|
return fmt.Errorf(`cannot obtain tsdb status for date=%d, topN=%d: %w`, date, topN, err)
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
WriteTSDBStatusResponse(bw, status)
|
WriteTSDBStatusResponse(bw, status)
|
||||||
|
@ -760,7 +760,7 @@ func LabelsHandler(startTime time.Time, w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
WriteLabelsResponse(bw, labels)
|
WriteLabelsResponse(bw, labels)
|
||||||
|
@ -826,7 +826,7 @@ func SeriesCountHandler(startTime time.Time, w http.ResponseWriter, r *http.Requ
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot obtain series count: %w", err)
|
return fmt.Errorf("cannot obtain series count: %w", err)
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
WriteSeriesCountResponse(bw, n)
|
WriteSeriesCountResponse(bw, n)
|
||||||
|
@ -883,7 +883,7 @@ func SeriesHandler(startTime time.Time, w http.ResponseWriter, r *http.Request)
|
||||||
return fmt.Errorf("cannot fetch data for %q: %w", sq, err)
|
return fmt.Errorf("cannot fetch data for %q: %w", sq, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
resultsCh := make(chan *quicktemplate.ByteBuffer)
|
resultsCh := make(chan *quicktemplate.ByteBuffer)
|
||||||
|
@ -1020,7 +1020,7 @@ func QueryHandler(startTime time.Time, w http.ResponseWriter, r *http.Request) e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
WriteQueryResponse(bw, result)
|
WriteQueryResponse(bw, result)
|
||||||
|
@ -1119,7 +1119,7 @@ func queryRangeHandler(startTime time.Time, w http.ResponseWriter, query string,
|
||||||
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/153
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/153
|
||||||
result = removeEmptyValuesAndTimeseries(result)
|
result = removeEmptyValuesAndTimeseries(result)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
bw := bufferedwriter.Get(w)
|
bw := bufferedwriter.Get(w)
|
||||||
defer bufferedwriter.Put(bw)
|
defer bufferedwriter.Put(bw)
|
||||||
WriteQueryRangeResponse(bw, result)
|
WriteQueryRangeResponse(bw, result)
|
||||||
|
|
|
@ -251,7 +251,7 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
|
|
||||||
switch path {
|
switch path {
|
||||||
case "/create":
|
case "/create":
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
snapshotPath, err := Storage.CreateSnapshot()
|
snapshotPath, err := Storage.CreateSnapshot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("cannot create snapshot: %w", err)
|
err = fmt.Errorf("cannot create snapshot: %w", err)
|
||||||
|
@ -265,7 +265,7 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case "/list":
|
case "/list":
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
snapshots, err := Storage.ListSnapshots()
|
snapshots, err := Storage.ListSnapshots()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("cannot list snapshots: %w", err)
|
err = fmt.Errorf("cannot list snapshots: %w", err)
|
||||||
|
@ -282,7 +282,7 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
fmt.Fprintf(w, `]}`)
|
fmt.Fprintf(w, `]}`)
|
||||||
return true
|
return true
|
||||||
case "/delete":
|
case "/delete":
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
snapshotName := r.FormValue("snapshot")
|
snapshotName := r.FormValue("snapshot")
|
||||||
if err := Storage.DeleteSnapshot(snapshotName); err != nil {
|
if err := Storage.DeleteSnapshot(snapshotName); err != nil {
|
||||||
err = fmt.Errorf("cannot delete snapshot %q: %w", snapshotName, err)
|
err = fmt.Errorf("cannot delete snapshot %q: %w", snapshotName, err)
|
||||||
|
@ -292,7 +292,7 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
fmt.Fprintf(w, `{"status":"ok"}`)
|
fmt.Fprintf(w, `{"status":"ok"}`)
|
||||||
return true
|
return true
|
||||||
case "/delete_all":
|
case "/delete_all":
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
snapshots, err := Storage.ListSnapshots()
|
snapshots, err := Storage.ListSnapshots()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("cannot list snapshots: %w", err)
|
err = fmt.Errorf("cannot list snapshots: %w", err)
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
* FEATURE: add `-search.treatDotsAsIsInRegexps` command-line flag, which can be used for automatic escaping of dots in regexp label filters used in queries.
|
* FEATURE: add `-search.treatDotsAsIsInRegexps` command-line flag, which can be used for automatic escaping of dots in regexp label filters used in queries.
|
||||||
For example, if `-search.treatDotsAsIsInRegexps` is set, then the query `foo{bar=~"aaa.bb.cc|dd.eee"}` is automatically converted to `foo{bar=~"aaa\\.bb\\.cc|dd\\.eee"}`.
|
For example, if `-search.treatDotsAsIsInRegexps` is set, then the query `foo{bar=~"aaa.bb.cc|dd.eee"}` is automatically converted to `foo{bar=~"aaa\\.bb\\.cc|dd\\.eee"}`.
|
||||||
This may be useful for querying Graphite data.
|
This may be useful for querying Graphite data.
|
||||||
|
* FEATURE: consistently return text-based HTTP responses such as `plain/text` and `application/json` with `charset=utf-8`.
|
||||||
|
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/897
|
||||||
|
|
||||||
* BUGFIX: do not return data points in the end of the selected time range for time series ending in the middle of the selected time range.
|
* BUGFIX: do not return data points in the end of the selected time range for time series ending in the middle of the selected time range.
|
||||||
See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/887 and https://github.com/VictoriaMetrics/VictoriaMetrics/issues/845
|
See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/887 and https://github.com/VictoriaMetrics/VictoriaMetrics/issues/845
|
||||||
|
|
|
@ -208,7 +208,7 @@ func handlerWrapper(s *server, w http.ResponseWriter, r *http.Request, rh Reques
|
||||||
r.URL.Path = path
|
r.URL.Path = path
|
||||||
switch r.URL.Path {
|
switch r.URL.Path {
|
||||||
case "/health":
|
case "/health":
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
deadline := atomic.LoadInt64(&s.shutdownDelayDeadline)
|
deadline := atomic.LoadInt64(&s.shutdownDelayDeadline)
|
||||||
if deadline <= 0 {
|
if deadline <= 0 {
|
||||||
w.Write([]byte("OK"))
|
w.Write([]byte("OK"))
|
||||||
|
@ -244,7 +244,7 @@ func handlerWrapper(s *server, w http.ResponseWriter, r *http.Request, rh Reques
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
WritePrometheusMetrics(w)
|
WritePrometheusMetrics(w)
|
||||||
metricsHandlerDuration.UpdateDuration(startTime)
|
metricsHandlerDuration.UpdateDuration(startTime)
|
||||||
return
|
return
|
||||||
|
@ -395,7 +395,7 @@ func (zrw *gzipResponseWriter) Write(p []byte) (int, error) {
|
||||||
if h.Get("Content-Type") == "" {
|
if h.Get("Content-Type") == "" {
|
||||||
// Disable auto-detection of content-type, since it
|
// Disable auto-detection of content-type, since it
|
||||||
// is incorrectly detected after the compression.
|
// is incorrectly detected after the compression.
|
||||||
h.Set("Content-Type", "text/html")
|
h.Set("Content-Type", "text/html; charset=utf-8")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zrw.writeHeader()
|
zrw.writeHeader()
|
||||||
|
|
Loading…
Reference in a new issue