some content negotiation!

This commit is contained in:
Owen Williams 2024-02-08 14:41:13 -05:00
parent cffe382b6c
commit ed92255636
11 changed files with 1318 additions and 80 deletions

View file

@ -228,8 +228,9 @@ func (c *flagConfig) setFeatureListOptions(logger log.Logger) error {
config.DefaultGlobalConfig.ScrapeProtocols = config.DefaultProtoFirstScrapeProtocols
level.Info(logger).Log("msg", "Experimental created timestamp zero ingestion enabled. Changed default scrape_protocols to prefer PrometheusProto format.", "global.scrape_protocols", fmt.Sprintf("%v", config.DefaultGlobalConfig.ScrapeProtocols))
case "utf8-names":
config.DefaultConfig.GlobalConfig.AllowUTF8Names = true
config.DefaultGlobalConfig.AllowUTF8Names = true
model.NameValidationScheme = model.UTF8Validation
level.Info(logger).Log("msg", "Experimental utf8 support enabled")
case "":
continue
case "promql-at-modifier", "promql-negative-offset":
@ -450,9 +451,7 @@ func main() {
a.Flag("scrape.discovery-reload-interval", "Interval used by scrape manager to throttle target groups updates.").
Hidden().Default("5s").SetValue(&cfg.scrape.DiscoveryReloadInterval)
a.Flag("scrape.name-escaping-scheme", "method to escape legacy invalid names when sending to an old version of prometheus. can be one of values (default), underscores, or dots").Default(scrape.DefaultNameEscapingScheme.String()).StringVar(&cfg.nameEscapingScheme)
a.Flag("enable-feature", "Comma separated feature names to enable. Valid options: agent, auto-gomemlimit, exemplar-storage, expand-external-labels, memory-snapshot-on-shutdown, promql-at-modifier, promql-negative-offset, promql-per-step-stats, promql-experimental-functions, remote-write-receiver (DEPRECATED), extra-scrape-metrics, new-service-discovery-manager, auto-gomaxprocs, no-default-scrape-port, native-histograms, otlp-write-receiver, utf8-names. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details.").
a.Flag("enable-feature", "Comma separated feature names to enable. Valid options: agent, exemplar-storage, expand-external-labels, memory-snapshot-on-shutdown, promql-at-modifier, promql-negative-offset, promql-per-step-stats, promql-experimental-functions, remote-write-receiver (DEPRECATED), extra-scrape-metrics, new-service-discovery-manager, auto-gomaxprocs, no-default-scrape-port, native-histograms, otlp-write-receiver, utf8-names. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details.").
Default("").StringsVar(&cfg.featureList)
promlogflag.AddFlags(a, &cfg.promlogConfig)

View file

@ -102,6 +102,7 @@ func PushMetrics(url *url.URL, roundTripper http.RoundTripper, headers map[strin
}
func parseAndPushMetrics(client *remote.Client, data []byte, labels map[string]string) bool {
// XXXXX ok we need communication between this call (it should escape)
metricsData, err := fmtutil.MetricTextToWriteRequest(bytes.NewReader(data), labels)
if err != nil {
fmt.Fprintln(os.Stderr, " FAILED:", err)
@ -116,6 +117,7 @@ func parseAndPushMetrics(client *remote.Client, data []byte, labels map[string]s
// Encode the request body into snappy encoding.
compressed := snappy.Encode(nil, raw)
// XXXXXXXXX and this call to store (which sets the content headers)
err = client.Store(context.Background(), compressed, 0)
if err != nil {
fmt.Fprintln(os.Stderr, " FAILED:", err)

2
go.mod
View file

@ -215,5 +215,3 @@ exclude (
github.com/grpc-ecosystem/grpc-gateway v1.14.7
google.golang.org/api v0.30.0
)
replace github.com/prometheus/client_golang => /home/owilliams/src/grafana/client_golang

1346
go.sum

File diff suppressed because it is too large Load diff

View file

@ -85,6 +85,10 @@ func New(b []byte, contentType string, parseClassicHistograms bool) (Parser, err
return NewPromParser(b), nil
}
// XXXX looks like this could be a place to decide if UTF8 is ok?? or is this
// all about we need a global option ---- yeah I think prometheus is either
// utf8 on and some preferred escaping, or its utf8 off. not per scrape target.
// In wihch case, nothing needs to change here.
mediaType, _, err := mime.ParseMediaType(contentType)
if err != nil {
return NewPromParser(b), err

View file

@ -26,7 +26,6 @@ import (
"github.com/prometheus/common/model"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels"

View file

@ -301,10 +301,10 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
}
func TestUTF8OpenMetricsParse(t *testing.T) {
// model.NameValidationScheme = model.UTF8Validation
// defer func(){
// model.NameValidationScheme = model.LegacyValidation
// }()
model.NameValidationScheme = model.UTF8Validation
defer func(){
model.NameValidationScheme = model.LegacyValidation
}()
input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations.
# TYPE "go.gc_duration_seconds" summary
@ -324,7 +324,7 @@ func TestUTF8OpenMetricsParse(t *testing.T) {
m string
t *int64
v float64
typ MetricType
typ model.MetricType
help string
unit string
comment string
@ -335,7 +335,7 @@ func TestUTF8OpenMetricsParse(t *testing.T) {
help: "A summary of the GC invocation durations.",
}, {
m: "go.gc_duration_seconds",
typ: MetricTypeSummary,
typ: model.MetricTypeSummary,
}, {
m: "go.gc_duration_seconds",
unit: "seconds",

View file

@ -28,7 +28,6 @@ import (
"github.com/prometheus/common/model"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels"

View file

@ -219,10 +219,10 @@ testmetric{label="\"bar\""} 1`
}
func TestUTF8PromParse(t *testing.T) {
// model.NameValidationScheme = model.UTF8Validation
// defer func() {
// model.NameValidationScheme = model.LegacyValidation
// }()
model.NameValidationScheme = model.UTF8Validation
defer func() {
model.NameValidationScheme = model.LegacyValidation
}()
input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations.
# TYPE "go.gc_duration_seconds" summary
@ -242,7 +242,7 @@ func TestUTF8PromParse(t *testing.T) {
m string
t *int64
v float64
typ MetricType
typ model.MetricType
help string
comment string
}{
@ -251,7 +251,7 @@ func TestUTF8PromParse(t *testing.T) {
help: "A summary of the GC invocation durations.",
}, {
m: "go.gc_duration_seconds",
typ: MetricTypeSummary,
typ: model.MetricTypeSummary,
}, {
m: `{"go.gc_duration_seconds",quantile="0"}`,
v: 4.9351e-05,
@ -597,7 +597,7 @@ func BenchmarkParse(b *testing.B) {
for i := 0; i < b.N; i += promtestdataSampleCount {
decSamples := make(model.Vector, 0, 50)
sdec := expfmt.SampleDecoder{
Dec: expfmt.NewDecoder(bytes.NewReader(buf), expfmt.FmtText),
Dec: expfmt.NewDecoder(bytes.NewReader(buf), expfmt.FmtText_1_0_0),
Opts: &expfmt.DecodeOptions{
Timestamp: model.TimeFromUnixNano(0),
},

View file

@ -2332,10 +2332,12 @@ func TestTargetScraperScrapeOK(t *testing.T) {
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
accept := r.Header.Get("Accept")
if protobufParsing {
require.True(t, strings.HasPrefix(accept, "application/vnd.google.protobuf;"),
"Expected Accept header to prefer application/vnd.google.protobuf.")
accept := r.Header.Get("Accept")
if !strings.HasPrefix(accept, "application/vnd.google.protobuf;") {
t.Errorf("Expected Accept header to prefer application/vnd.google.protobuf, got %q", accept)
}
}
if strings.Contains(accept, "escaping=allow-utf-8") {
if strings.Contains(accept, "validchars=utf8") {
t.Errorf("Expected Accept header not to allow utf8, got %q", accept)
}

View file

@ -274,6 +274,7 @@ func (c *Client) Read(ctx context.Context, query *prompb.Query) (*prompb.QueryRe
c.readQueries.Inc()
defer c.readQueries.Dec()
// XXXXXX based on content negotiation we may need to escape the query. (If the other side is old)
req := &prompb.ReadRequest{
// TODO: Support batching multiple queries into one read request,
// as the protobuf interface allows for it.