Merge pull request #13341 from prometheus/prw2.0-main1

Merge main into remote-write-2.0 for latest changes.
This commit is contained in:
Bartlomiej Plotka 2023-12-31 11:15:59 +01:00 committed by GitHub
commit b67a61ac89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 470 additions and 329 deletions

View file

@ -568,6 +568,7 @@ var expectedConf = &Config{
ServiceDiscoveryConfigs: discovery.Configs{ ServiceDiscoveryConfigs: discovery.Configs{
&xds.KumaSDConfig{ &xds.KumaSDConfig{
Server: "http://kuma-control-plane.kuma-system.svc:5676", Server: "http://kuma-control-plane.kuma-system.svc:5676",
ClientID: "main-prometheus",
HTTPClientConfig: config.DefaultHTTPClientConfig, HTTPClientConfig: config.DefaultHTTPClientConfig,
RefreshInterval: model.Duration(15 * time.Second), RefreshInterval: model.Duration(15 * time.Second),
FetchTimeout: model.Duration(2 * time.Minute), FetchTimeout: model.Duration(2 * time.Minute),

View file

@ -221,6 +221,7 @@ scrape_configs:
kuma_sd_configs: kuma_sd_configs:
- server: http://kuma-control-plane.kuma-system.svc:5676 - server: http://kuma-control-plane.kuma-system.svc:5676
client_id: main-prometheus
- job_name: service-marathon - job_name: service-marathon
marathon_sd_configs: marathon_sd_configs:

View file

@ -108,6 +108,7 @@ scrape_configs:
kuma_sd_configs: kuma_sd_configs:
- server: http://kuma-control-plane.kuma-system.svc:5676 - server: http://kuma-control-plane.kuma-system.svc:5676
client_id: main-prometheus
marathon_sd_configs: marathon_sd_configs:
- servers: - servers:

View file

@ -30,8 +30,8 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4"
cache "github.com/Code-Hex/go-generics-cache" cache "github.com/Code-Hex/go-generics-cache"
"github.com/Code-Hex/go-generics-cache/policy/lru" "github.com/Code-Hex/go-generics-cache/policy/lru"
"github.com/go-kit/log" "github.com/go-kit/log"
@ -411,29 +411,19 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
} else { } else {
if vm.ScaleSet == "" { if vm.ScaleSet == "" {
networkInterface, err = client.getVMNetworkInterfaceByID(ctx, nicID) networkInterface, err = client.getVMNetworkInterfaceByID(ctx, nicID)
if err != nil {
if errors.Is(err, errorNotFound) {
level.Warn(d.logger).Log("msg", "Network interface does not exist", "name", nicID, "err", err)
} else {
ch <- target{labelSet: nil, err: err}
}
// Get out of this routine because we cannot continue without a network interface.
return
}
d.addToCache(nicID, networkInterface)
} else { } else {
networkInterface, err = client.getVMScaleSetVMNetworkInterfaceByID(ctx, nicID, vm.ScaleSet, vm.InstanceID) networkInterface, err = client.getVMScaleSetVMNetworkInterfaceByID(ctx, nicID, vm.ScaleSet, vm.InstanceID)
if err != nil {
if errors.Is(err, errorNotFound) {
level.Warn(d.logger).Log("msg", "Network interface does not exist", "name", nicID, "err", err)
} else {
ch <- target{labelSet: nil, err: err}
}
// Get out of this routine because we cannot continue without a network interface.
return
}
d.addToCache(nicID, networkInterface)
} }
if err != nil {
if errors.Is(err, errorNotFound) {
level.Warn(d.logger).Log("msg", "Network interface does not exist", "name", nicID, "err", err)
} else {
ch <- target{labelSet: nil, err: err}
}
// Get out of this routine because we cannot continue without a network interface.
return
}
d.addToCache(nicID, networkInterface)
} }
if networkInterface.Properties == nil { if networkInterface.Properties == nil {

View file

@ -17,7 +17,7 @@ import (
"testing" "testing"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.uber.org/goleak" "go.uber.org/goleak"
) )

View file

@ -155,10 +155,14 @@ func kumaMadsV1ResourceParser(resources []*anypb.Any, typeURL string) ([]model.L
func NewKumaHTTPDiscovery(conf *KumaSDConfig, logger log.Logger, reg prometheus.Registerer) (discovery.Discoverer, error) { func NewKumaHTTPDiscovery(conf *KumaSDConfig, logger log.Logger, reg prometheus.Registerer) (discovery.Discoverer, error) {
// Default to "prometheus" if hostname is unavailable. // Default to "prometheus" if hostname is unavailable.
clientID, err := osutil.GetFQDN() clientID := conf.ClientID
if err != nil { if clientID == "" {
level.Debug(logger).Log("msg", "error getting FQDN", "err", err) var err error
clientID = "prometheus" clientID, err = osutil.GetFQDN()
if err != nil {
level.Debug(logger).Log("msg", "error getting FQDN", "err", err)
clientID = "prometheus"
}
} }
clientConfig := &HTTPResourceClientConfig{ clientConfig := &HTTPResourceClientConfig{

View file

@ -205,7 +205,7 @@ func TestNewKumaHTTPDiscovery(t *testing.T) {
require.True(t, ok) require.True(t, ok)
require.Equal(t, kumaConf.Server, resClient.Server()) require.Equal(t, kumaConf.Server, resClient.Server())
require.Equal(t, KumaMadsV1ResourceTypeURL, resClient.ResourceTypeURL()) require.Equal(t, KumaMadsV1ResourceTypeURL, resClient.ResourceTypeURL())
require.NotEmpty(t, resClient.ID()) require.Equal(t, kumaConf.ClientID, resClient.ID())
require.Equal(t, KumaMadsV1ResourceType, resClient.config.ResourceType) require.Equal(t, KumaMadsV1ResourceType, resClient.config.ResourceType)
} }

View file

@ -55,6 +55,7 @@ type SDConfig struct {
RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"` RefreshInterval model.Duration `yaml:"refresh_interval,omitempty"`
FetchTimeout model.Duration `yaml:"fetch_timeout,omitempty"` FetchTimeout model.Duration `yaml:"fetch_timeout,omitempty"`
Server string `yaml:"server,omitempty"` Server string `yaml:"server,omitempty"`
ClientID string `yaml:"client_id,omitempty"`
} }
// mustRegisterMessage registers the provided message type in the typeRegistry, and panics // mustRegisterMessage registers the provided message type in the typeRegistry, and panics

View file

@ -36,6 +36,7 @@ var (
sdConf = SDConfig{ sdConf = SDConfig{
Server: "http://127.0.0.1", Server: "http://127.0.0.1",
RefreshInterval: model.Duration(10 * time.Second), RefreshInterval: model.Duration(10 * time.Second),
ClientID: "test-id",
} }
testFetchFailuresCount = prometheus.NewCounter( testFetchFailuresCount = prometheus.NewCounter(

View file

@ -2230,6 +2230,11 @@ See below for the configuration options for Kuma MonitoringAssignment discovery:
# Address of the Kuma Control Plane's MADS xDS server. # Address of the Kuma Control Plane's MADS xDS server.
server: <string> server: <string>
# Client id is used by Kuma Control Plane to compute Monitoring Assignment for specific Prometheus backend.
# This is useful when migrating between multiple Prometheus backends, or having separate backend for each Mesh.
# When not specified, system hostname/fqdn will be used if available, if not `prometheus` will be used.
[ client_id: <string> ]
# The time to wait between polling update requests. # The time to wait between polling update requests.
[ refresh_interval: <duration> | default = 30s ] [ refresh_interval: <duration> | default = 30s ]

9
go.mod
View file

@ -5,8 +5,9 @@ go 1.20
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.3.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0
github.com/Code-Hex/go-generics-cache v1.3.1
github.com/alecthomas/kingpin/v2 v2.4.0 github.com/alecthomas/kingpin/v2 v2.4.0
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9
github.com/aws/aws-sdk-go v1.48.14 github.com/aws/aws-sdk-go v1.48.14
@ -47,7 +48,7 @@ require (
github.com/prometheus/alertmanager v0.26.0 github.com/prometheus/alertmanager v0.26.0
github.com/prometheus/client_golang v1.17.0 github.com/prometheus/client_golang v1.17.0
github.com/prometheus/client_model v0.5.0 github.com/prometheus/client_model v0.5.0
github.com/prometheus/common v0.45.0 github.com/prometheus/common v0.45.1-0.20231122191551-832cd6e99f99
github.com/prometheus/common/assets v0.2.0 github.com/prometheus/common/assets v0.2.0
github.com/prometheus/common/sigv4 v0.1.0 github.com/prometheus/common/sigv4 v0.1.0
github.com/prometheus/exporter-toolkit v0.10.0 github.com/prometheus/exporter-toolkit v0.10.0
@ -93,9 +94,7 @@ require (
cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute v1.23.3 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
github.com/Code-Hex/go-generics-cache v1.3.1
github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/armon/go-metrics v0.4.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect

18
go.sum
View file

@ -40,14 +40,12 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZM
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 h1:UPeCRD+XY7QlaGQte2EVI2iOcWvUYA2XY8w5T/8v0NQ= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.3.0 h1:qgs/VAMSR+9qFhwTw4OwF2NbVuw+2m83pVZJjqkKQMw=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1/go.mod h1:oGV6NlB0cvi1ZbYRR2UN44QHxWFyGk+iylgD0qaMXjA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.3.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0 h1:QM6sE5k2ZT/vI5BEe0r7mqjsUSnhVBFbOsVkEuaEfiA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.1.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1 h1:bWh0Z2rOEDfB/ywv/l0iHN1JgyazE6kW/aIA89+CEK0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2 v2.2.1/go.mod h1:Bzf34hhAE9NSxailk8xVeLEZbUjOXcC+GnU1mMKdhLw=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk=
@ -655,8 +653,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/common v0.45.1-0.20231122191551-832cd6e99f99 h1:V5ajRiLiCQGO+ggTr+07gMUcTqlIMMkDBfrJe5zKLmc=
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/common v0.45.1-0.20231122191551-832cd6e99f99/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM= github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM=
github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI=
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=

View file

@ -13,11 +13,11 @@
package metadata package metadata
import "github.com/prometheus/prometheus/model/textparse" import "github.com/prometheus/common/model"
// Metadata stores a series' metadata information. // Metadata stores a series' metadata information.
type Metadata struct { type Metadata struct {
Type textparse.MetricType Type model.MetricType
Unit string Unit string
Help string Help string
} }

View file

@ -108,6 +108,10 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
if c.Regex.Regexp == nil { if c.Regex.Regexp == nil {
c.Regex = MustNewRegexp("") c.Regex = MustNewRegexp("")
} }
return c.Validate()
}
func (c *Config) Validate() error {
if c.Action == "" { if c.Action == "" {
return fmt.Errorf("relabel action cannot be empty") return fmt.Errorf("relabel action cannot be empty")
} }
@ -117,7 +121,13 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
if (c.Action == Replace || c.Action == HashMod || c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.TargetLabel == "" { if (c.Action == Replace || c.Action == HashMod || c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.TargetLabel == "" {
return fmt.Errorf("relabel configuration for %s action requires 'target_label' value", c.Action) return fmt.Errorf("relabel configuration for %s action requires 'target_label' value", c.Action)
} }
if (c.Action == Replace || c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && !relabelTarget.MatchString(c.TargetLabel) { if c.Action == Replace && !strings.Contains(c.TargetLabel, "$") && !model.LabelName(c.TargetLabel).IsValid() {
return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
}
if c.Action == Replace && strings.Contains(c.TargetLabel, "$") && !relabelTarget.MatchString(c.TargetLabel) {
return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
}
if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && !model.LabelName(c.TargetLabel).IsValid() {
return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action) return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
} }
if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.Replacement != DefaultRelabelConfig.Replacement { if (c.Action == Lowercase || c.Action == Uppercase || c.Action == KeepEqual || c.Action == DropEqual) && c.Replacement != DefaultRelabelConfig.Replacement {
@ -264,12 +274,11 @@ func relabel(cfg *Config, lb *labels.Builder) (keep bool) {
} }
target := model.LabelName(cfg.Regex.ExpandString([]byte{}, cfg.TargetLabel, val, indexes)) target := model.LabelName(cfg.Regex.ExpandString([]byte{}, cfg.TargetLabel, val, indexes))
if !target.IsValid() { if !target.IsValid() {
lb.Del(cfg.TargetLabel)
break break
} }
res := cfg.Regex.ExpandString([]byte{}, cfg.Replacement, val, indexes) res := cfg.Regex.ExpandString([]byte{}, cfg.Replacement, val, indexes)
if len(res) == 0 { if len(res) == 0 {
lb.Del(cfg.TargetLabel) lb.Del(string(target))
break break
} }
lb.Set(string(target), string(res)) lb.Set(string(target), string(res))

View file

@ -14,6 +14,7 @@
package relabel package relabel
import ( import (
"fmt"
"testing" "testing"
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
@ -213,6 +214,25 @@ func TestRelabel(t *testing.T) {
"a": "boo", "a": "boo",
}), }),
}, },
{
// Blank replacement should delete the label.
input: labels.FromMap(map[string]string{
"a": "foo",
"f": "baz",
}),
relabel: []*Config{
{
SourceLabels: model.LabelNames{"a"},
Regex: MustNewRegexp("(f).*"),
TargetLabel: "$1",
Replacement: "$2",
Action: Replace,
},
},
output: labels.FromMap(map[string]string{
"a": "foo",
}),
},
{ {
input: labels.FromMap(map[string]string{ input: labels.FromMap(map[string]string{
"a": "foo", "a": "foo",
@ -334,7 +354,7 @@ func TestRelabel(t *testing.T) {
}, },
{ // invalid target_labels { // invalid target_labels
input: labels.FromMap(map[string]string{ input: labels.FromMap(map[string]string{
"a": "some-name-value", "a": "some-name-0",
}), }),
relabel: []*Config{ relabel: []*Config{
{ {
@ -349,18 +369,18 @@ func TestRelabel(t *testing.T) {
Regex: MustNewRegexp("some-([^-]+)-([^,]+)"), Regex: MustNewRegexp("some-([^-]+)-([^,]+)"),
Action: Replace, Action: Replace,
Replacement: "${1}", Replacement: "${1}",
TargetLabel: "0${3}", TargetLabel: "${3}",
}, },
{ {
SourceLabels: model.LabelNames{"a"}, SourceLabels: model.LabelNames{"a"},
Regex: MustNewRegexp("some-([^-]+)-([^,]+)"), Regex: MustNewRegexp("some-([^-]+)(-[^,]+)"),
Action: Replace, Action: Replace,
Replacement: "${1}", Replacement: "${1}",
TargetLabel: "-${3}", TargetLabel: "${3}",
}, },
}, },
output: labels.FromMap(map[string]string{ output: labels.FromMap(map[string]string{
"a": "some-name-value", "a": "some-name-0",
}), }),
}, },
{ // more complex real-life like usecase { // more complex real-life like usecase
@ -565,6 +585,7 @@ func TestRelabel(t *testing.T) {
if cfg.Replacement == "" { if cfg.Replacement == "" {
cfg.Replacement = DefaultRelabelConfig.Replacement cfg.Replacement = DefaultRelabelConfig.Replacement
} }
require.NoError(t, cfg.Validate())
} }
res, keep := Process(test.input, test.relabel...) res, keep := Process(test.input, test.relabel...)
@ -575,6 +596,77 @@ func TestRelabel(t *testing.T) {
} }
} }
func TestRelabelValidate(t *testing.T) {
tests := []struct {
config Config
expected string
}{
{
config: Config{},
expected: `relabel action cannot be empty`,
},
{
config: Config{
Action: Replace,
},
expected: `requires 'target_label' value`,
},
{
config: Config{
Action: Lowercase,
},
expected: `requires 'target_label' value`,
},
{
config: Config{
Action: Lowercase,
Replacement: DefaultRelabelConfig.Replacement,
TargetLabel: "${3}",
},
expected: `"${3}" is invalid 'target_label'`,
},
{
config: Config{
SourceLabels: model.LabelNames{"a"},
Regex: MustNewRegexp("some-([^-]+)-([^,]+)"),
Action: Replace,
Replacement: "${1}",
TargetLabel: "${3}",
},
},
{
config: Config{
SourceLabels: model.LabelNames{"a"},
Regex: MustNewRegexp("some-([^-]+)-([^,]+)"),
Action: Replace,
Replacement: "${1}",
TargetLabel: "0${3}",
},
expected: `"0${3}" is invalid 'target_label'`,
},
{
config: Config{
SourceLabels: model.LabelNames{"a"},
Regex: MustNewRegexp("some-([^-]+)-([^,]+)"),
Action: Replace,
Replacement: "${1}",
TargetLabel: "-${3}",
},
expected: `"-${3}" is invalid 'target_label' for replace action`,
},
}
for i, test := range tests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
err := test.config.Validate()
if test.expected == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, test.expected)
}
})
}
}
func TestTargetLabelValidity(t *testing.T) { func TestTargetLabelValidity(t *testing.T) {
tests := []struct { tests := []struct {
str string str string

View file

@ -16,6 +16,8 @@ package textparse
import ( import (
"mime" "mime"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
@ -42,7 +44,7 @@ type Parser interface {
// Type returns the metric name and type in the current entry. // Type returns the metric name and type in the current entry.
// Must only be called after Next returned a type entry. // Must only be called after Next returned a type entry.
// The returned byte slices become invalid after the next call to Next. // The returned byte slices become invalid after the next call to Next.
Type() ([]byte, MetricType) Type() ([]byte, model.MetricType)
// Unit returns the metric name and unit in the current entry. // Unit returns the metric name and unit in the current entry.
// Must only be called after Next returned a unit entry. // Must only be called after Next returned a unit entry.
@ -109,17 +111,3 @@ const (
EntryUnit Entry = 4 EntryUnit Entry = 4
EntryHistogram Entry = 5 // A series with a native histogram as a value. EntryHistogram Entry = 5 // A series with a native histogram as a value.
) )
// MetricType represents metric type values.
type MetricType string
const (
MetricTypeCounter = MetricType("counter")
MetricTypeGauge = MetricType("gauge")
MetricTypeHistogram = MetricType("histogram")
MetricTypeGaugeHistogram = MetricType("gaugehistogram")
MetricTypeSummary = MetricType("summary")
MetricTypeInfo = MetricType("info")
MetricTypeStateset = MetricType("stateset")
MetricTypeUnknown = MetricType("unknown")
)

View file

@ -24,6 +24,8 @@ import (
"strings" "strings"
"unicode/utf8" "unicode/utf8"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
@ -74,7 +76,7 @@ type OpenMetricsParser struct {
builder labels.ScratchBuilder builder labels.ScratchBuilder
series []byte series []byte
text []byte text []byte
mtype MetricType mtype model.MetricType
val float64 val float64
ts int64 ts int64
hasTS bool hasTS bool
@ -126,7 +128,7 @@ func (p *OpenMetricsParser) Help() ([]byte, []byte) {
// Type returns the metric name and type in the current entry. // Type returns the metric name and type in the current entry.
// Must only be called after Next returned a type entry. // Must only be called after Next returned a type entry.
// The returned byte slices become invalid after the next call to Next. // The returned byte slices become invalid after the next call to Next.
func (p *OpenMetricsParser) Type() ([]byte, MetricType) { func (p *OpenMetricsParser) Type() ([]byte, model.MetricType) {
return p.l.b[p.offsets[0]:p.offsets[1]], p.mtype return p.l.b[p.offsets[0]:p.offsets[1]], p.mtype
} }
@ -272,21 +274,21 @@ func (p *OpenMetricsParser) Next() (Entry, error) {
case tType: case tType:
switch s := yoloString(p.text); s { switch s := yoloString(p.text); s {
case "counter": case "counter":
p.mtype = MetricTypeCounter p.mtype = model.MetricTypeCounter
case "gauge": case "gauge":
p.mtype = MetricTypeGauge p.mtype = model.MetricTypeGauge
case "histogram": case "histogram":
p.mtype = MetricTypeHistogram p.mtype = model.MetricTypeHistogram
case "gaugehistogram": case "gaugehistogram":
p.mtype = MetricTypeGaugeHistogram p.mtype = model.MetricTypeGaugeHistogram
case "summary": case "summary":
p.mtype = MetricTypeSummary p.mtype = model.MetricTypeSummary
case "info": case "info":
p.mtype = MetricTypeInfo p.mtype = model.MetricTypeInfo
case "stateset": case "stateset":
p.mtype = MetricTypeStateset p.mtype = model.MetricTypeStateset
case "unknown": case "unknown":
p.mtype = MetricTypeUnknown p.mtype = model.MetricTypeUnknown
default: default:
return EntryInvalid, fmt.Errorf("invalid metric type %q", s) return EntryInvalid, fmt.Errorf("invalid metric type %q", s)
} }

View file

@ -18,6 +18,7 @@ import (
"io" "io"
"testing" "testing"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/exemplar"
@ -77,7 +78,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
m string m string
t *int64 t *int64
v float64 v float64
typ MetricType typ model.MetricType
help string help string
unit string unit string
comment string comment string
@ -88,7 +89,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
help: "A summary of the GC invocation durations.", help: "A summary of the GC invocation durations.",
}, { }, {
m: "go_gc_duration_seconds", m: "go_gc_duration_seconds",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, { }, {
m: "go_gc_duration_seconds", m: "go_gc_duration_seconds",
unit: "seconds", unit: "seconds",
@ -130,7 +131,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
help: "Number of goroutines that currently exist.", help: "Number of goroutines that currently exist.",
}, { }, {
m: "go_goroutines", m: "go_goroutines",
typ: MetricTypeGauge, typ: model.MetricTypeGauge,
}, { }, {
m: `go_goroutines`, m: `go_goroutines`,
v: 33, v: 33,
@ -138,21 +139,21 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
lset: labels.FromStrings("__name__", "go_goroutines"), lset: labels.FromStrings("__name__", "go_goroutines"),
}, { }, {
m: "hh", m: "hh",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, { }, {
m: `hh_bucket{le="+Inf"}`, m: `hh_bucket{le="+Inf"}`,
v: 1, v: 1,
lset: labels.FromStrings("__name__", "hh_bucket", "le", "+Inf"), lset: labels.FromStrings("__name__", "hh_bucket", "le", "+Inf"),
}, { }, {
m: "gh", m: "gh",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, { }, {
m: `gh_bucket{le="+Inf"}`, m: `gh_bucket{le="+Inf"}`,
v: 1, v: 1,
lset: labels.FromStrings("__name__", "gh_bucket", "le", "+Inf"), lset: labels.FromStrings("__name__", "gh_bucket", "le", "+Inf"),
}, { }, {
m: "hhh", m: "hhh",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, { }, {
m: `hhh_bucket{le="+Inf"}`, m: `hhh_bucket{le="+Inf"}`,
v: 1, v: 1,
@ -165,7 +166,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "histogram-count-test"), Value: 4}, e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "histogram-count-test"), Value: 4},
}, { }, {
m: "ggh", m: "ggh",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, { }, {
m: `ggh_bucket{le="+Inf"}`, m: `ggh_bucket{le="+Inf"}`,
v: 1, v: 1,
@ -178,7 +179,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "gaugehistogram-count-test", "xx", "yy"), Value: 4, HasTs: true, Ts: 123123}, e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "gaugehistogram-count-test", "xx", "yy"), Value: 4, HasTs: true, Ts: 123123},
}, { }, {
m: "smr_seconds", m: "smr_seconds",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, { }, {
m: `smr_seconds_count`, m: `smr_seconds_count`,
v: 2, v: 2,
@ -191,14 +192,14 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "summary-sum-test"), Value: 1, HasTs: true, Ts: 123321}, e: &exemplar.Exemplar{Labels: labels.FromStrings("id", "summary-sum-test"), Value: 1, HasTs: true, Ts: 123321},
}, { }, {
m: "ii", m: "ii",
typ: MetricTypeInfo, typ: model.MetricTypeInfo,
}, { }, {
m: `ii{foo="bar"}`, m: `ii{foo="bar"}`,
v: 1, v: 1,
lset: labels.FromStrings("__name__", "ii", "foo", "bar"), lset: labels.FromStrings("__name__", "ii", "foo", "bar"),
}, { }, {
m: "ss", m: "ss",
typ: MetricTypeStateset, typ: model.MetricTypeStateset,
}, { }, {
m: `ss{ss="foo"}`, m: `ss{ss="foo"}`,
v: 1, v: 1,
@ -213,7 +214,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
lset: labels.FromStrings("A", "a", "__name__", "ss"), lset: labels.FromStrings("A", "a", "__name__", "ss"),
}, { }, {
m: "un", m: "un",
typ: MetricTypeUnknown, typ: model.MetricTypeUnknown,
}, { }, {
m: "_metric_starting_with_underscore", m: "_metric_starting_with_underscore",
v: 1, v: 1,
@ -228,7 +229,7 @@ foo_total 17.0 1520879607.789 # {id="counter-test"} 5`
lset: labels.FromStrings("__name__", "testmetric", "label", `"bar"`), lset: labels.FromStrings("__name__", "testmetric", "label", `"bar"`),
}, { }, {
m: "foo", m: "foo",
typ: MetricTypeCounter, typ: model.MetricTypeCounter,
}, { }, {
m: "foo_total", m: "foo_total",
v: 17, v: 17,

View file

@ -26,6 +26,8 @@ import (
"unicode/utf8" "unicode/utf8"
"unsafe" "unsafe"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
@ -146,7 +148,7 @@ type PromParser struct {
builder labels.ScratchBuilder builder labels.ScratchBuilder
series []byte series []byte
text []byte text []byte
mtype MetricType mtype model.MetricType
val float64 val float64
ts int64 ts int64
hasTS bool hasTS bool
@ -190,7 +192,7 @@ func (p *PromParser) Help() ([]byte, []byte) {
// Type returns the metric name and type in the current entry. // Type returns the metric name and type in the current entry.
// Must only be called after Next returned a type entry. // Must only be called after Next returned a type entry.
// The returned byte slices become invalid after the next call to Next. // The returned byte slices become invalid after the next call to Next.
func (p *PromParser) Type() ([]byte, MetricType) { func (p *PromParser) Type() ([]byte, model.MetricType) {
return p.l.b[p.offsets[0]:p.offsets[1]], p.mtype return p.l.b[p.offsets[0]:p.offsets[1]], p.mtype
} }
@ -305,15 +307,15 @@ func (p *PromParser) Next() (Entry, error) {
case tType: case tType:
switch s := yoloString(p.text); s { switch s := yoloString(p.text); s {
case "counter": case "counter":
p.mtype = MetricTypeCounter p.mtype = model.MetricTypeCounter
case "gauge": case "gauge":
p.mtype = MetricTypeGauge p.mtype = model.MetricTypeGauge
case "histogram": case "histogram":
p.mtype = MetricTypeHistogram p.mtype = model.MetricTypeHistogram
case "summary": case "summary":
p.mtype = MetricTypeSummary p.mtype = model.MetricTypeSummary
case "untyped": case "untyped":
p.mtype = MetricTypeUnknown p.mtype = model.MetricTypeUnknown
default: default:
return EntryInvalid, fmt.Errorf("invalid metric type %q", s) return EntryInvalid, fmt.Errorf("invalid metric type %q", s)
} }

View file

@ -65,7 +65,7 @@ testmetric{label="\"bar\""} 1`
m string m string
t *int64 t *int64
v float64 v float64
typ MetricType typ model.MetricType
help string help string
comment string comment string
}{ }{
@ -74,7 +74,7 @@ testmetric{label="\"bar\""} 1`
help: "A summary of the GC invocation durations.", help: "A summary of the GC invocation durations.",
}, { }, {
m: "go_gc_duration_seconds", m: "go_gc_duration_seconds",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, { }, {
m: `go_gc_duration_seconds{quantile="0"}`, m: `go_gc_duration_seconds{quantile="0"}`,
v: 4.9351e-05, v: 4.9351e-05,
@ -142,7 +142,7 @@ testmetric{label="\"bar\""} 1`
help: "Number of goroutines that currently exist.", help: "Number of goroutines that currently exist.",
}, { }, {
m: "go_goroutines", m: "go_goroutines",
typ: MetricTypeGauge, typ: model.MetricTypeGauge,
}, { }, {
m: `go_goroutines`, m: `go_goroutines`,
v: 33, v: 33,

View file

@ -252,21 +252,21 @@ func (p *ProtobufParser) Help() ([]byte, []byte) {
// Type returns the metric name and type in the current entry. // Type returns the metric name and type in the current entry.
// Must only be called after Next returned a type entry. // Must only be called after Next returned a type entry.
// The returned byte slices become invalid after the next call to Next. // The returned byte slices become invalid after the next call to Next.
func (p *ProtobufParser) Type() ([]byte, MetricType) { func (p *ProtobufParser) Type() ([]byte, model.MetricType) {
n := p.metricBytes.Bytes() n := p.metricBytes.Bytes()
switch p.mf.GetType() { switch p.mf.GetType() {
case dto.MetricType_COUNTER: case dto.MetricType_COUNTER:
return n, MetricTypeCounter return n, model.MetricTypeCounter
case dto.MetricType_GAUGE: case dto.MetricType_GAUGE:
return n, MetricTypeGauge return n, model.MetricTypeGauge
case dto.MetricType_HISTOGRAM: case dto.MetricType_HISTOGRAM:
return n, MetricTypeHistogram return n, model.MetricTypeHistogram
case dto.MetricType_GAUGE_HISTOGRAM: case dto.MetricType_GAUGE_HISTOGRAM:
return n, MetricTypeGaugeHistogram return n, model.MetricTypeGaugeHistogram
case dto.MetricType_SUMMARY: case dto.MetricType_SUMMARY:
return n, MetricTypeSummary return n, model.MetricTypeSummary
} }
return n, MetricTypeUnknown return n, model.MetricTypeUnknown
} }
// Unit always returns (nil, nil) because units aren't supported by the protobuf // Unit always returns (nil, nil) because units aren't supported by the protobuf

View file

@ -21,6 +21,7 @@ import (
"testing" "testing"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/exemplar"
@ -622,7 +623,7 @@ func TestProtobufParse(t *testing.T) {
m string m string
t int64 t int64
v float64 v float64
typ MetricType typ model.MetricType
help string help string
unit string unit string
comment string comment string
@ -649,7 +650,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "go_build_info", m: "go_build_info",
typ: MetricTypeGauge, typ: model.MetricTypeGauge,
}, },
{ {
m: "go_build_info\xFFchecksum\xFF\xFFpath\xFFgithub.com/prometheus/client_golang\xFFversion\xFF(devel)", m: "go_build_info\xFFchecksum\xFF\xFFpath\xFFgithub.com/prometheus/client_golang\xFFversion\xFF(devel)",
@ -667,7 +668,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "go_memstats_alloc_bytes_total", m: "go_memstats_alloc_bytes_total",
typ: MetricTypeCounter, typ: model.MetricTypeCounter,
}, },
{ {
m: "go_memstats_alloc_bytes_total", m: "go_memstats_alloc_bytes_total",
@ -685,7 +686,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "something_untyped", m: "something_untyped",
typ: MetricTypeUnknown, typ: model.MetricTypeUnknown,
}, },
{ {
m: "something_untyped", m: "something_untyped",
@ -701,7 +702,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_histogram", m: "test_histogram",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ {
m: "test_histogram", m: "test_histogram",
@ -736,7 +737,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_gauge_histogram", m: "test_gauge_histogram",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, },
{ {
m: "test_gauge_histogram", m: "test_gauge_histogram",
@ -772,7 +773,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_float_histogram", m: "test_float_histogram",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ {
m: "test_float_histogram", m: "test_float_histogram",
@ -807,7 +808,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_gauge_float_histogram", m: "test_gauge_float_histogram",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, },
{ {
m: "test_gauge_float_histogram", m: "test_gauge_float_histogram",
@ -843,7 +844,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_histogram2", m: "test_histogram2",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ {
m: "test_histogram2_count", m: "test_histogram2_count",
@ -903,7 +904,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_histogram_family", m: "test_histogram_family",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ {
m: "test_histogram_family\xfffoo\xffbar", m: "test_histogram_family\xfffoo\xffbar",
@ -947,7 +948,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_float_histogram_with_zerothreshold_zero", m: "test_float_histogram_with_zerothreshold_zero",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ {
m: "test_float_histogram_with_zerothreshold_zero", m: "test_float_histogram_with_zerothreshold_zero",
@ -971,7 +972,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "rpc_durations_seconds", m: "rpc_durations_seconds",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, },
{ {
m: "rpc_durations_seconds_count\xffservice\xffexponential", m: "rpc_durations_seconds_count\xffservice\xffexponential",
@ -1022,7 +1023,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "without_quantiles", m: "without_quantiles",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, },
{ {
m: "without_quantiles_count", m: "without_quantiles_count",
@ -1044,7 +1045,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "empty_histogram", m: "empty_histogram",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ {
m: "empty_histogram", m: "empty_histogram",
@ -1063,7 +1064,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_counter_with_createdtimestamp", m: "test_counter_with_createdtimestamp",
typ: MetricTypeCounter, typ: model.MetricTypeCounter,
}, },
{ {
m: "test_counter_with_createdtimestamp", m: "test_counter_with_createdtimestamp",
@ -1079,7 +1080,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_summary_with_createdtimestamp", m: "test_summary_with_createdtimestamp",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, },
{ {
m: "test_summary_with_createdtimestamp_count", m: "test_summary_with_createdtimestamp_count",
@ -1103,7 +1104,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_histogram_with_createdtimestamp", m: "test_histogram_with_createdtimestamp",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ {
m: "test_histogram_with_createdtimestamp", m: "test_histogram_with_createdtimestamp",
@ -1123,7 +1124,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ {
m: "test_gaugehistogram_with_createdtimestamp", m: "test_gaugehistogram_with_createdtimestamp",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, },
{ {
m: "test_gaugehistogram_with_createdtimestamp", m: "test_gaugehistogram_with_createdtimestamp",
@ -1149,7 +1150,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 1 { // 1
m: "go_build_info", m: "go_build_info",
typ: MetricTypeGauge, typ: model.MetricTypeGauge,
}, },
{ // 2 { // 2
m: "go_build_info\xFFchecksum\xFF\xFFpath\xFFgithub.com/prometheus/client_golang\xFFversion\xFF(devel)", m: "go_build_info\xFFchecksum\xFF\xFFpath\xFFgithub.com/prometheus/client_golang\xFFversion\xFF(devel)",
@ -1167,7 +1168,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 4 { // 4
m: "go_memstats_alloc_bytes_total", m: "go_memstats_alloc_bytes_total",
typ: MetricTypeCounter, typ: model.MetricTypeCounter,
}, },
{ // 5 { // 5
m: "go_memstats_alloc_bytes_total", m: "go_memstats_alloc_bytes_total",
@ -1185,7 +1186,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 7 { // 7
m: "something_untyped", m: "something_untyped",
typ: MetricTypeUnknown, typ: model.MetricTypeUnknown,
}, },
{ // 8 { // 8
m: "something_untyped", m: "something_untyped",
@ -1201,7 +1202,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 10 { // 10
m: "test_histogram", m: "test_histogram",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ // 11 { // 11
m: "test_histogram", m: "test_histogram",
@ -1294,7 +1295,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 19 { // 19
m: "test_gauge_histogram", m: "test_gauge_histogram",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, },
{ // 20 { // 20
m: "test_gauge_histogram", m: "test_gauge_histogram",
@ -1388,7 +1389,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 28 { // 28
m: "test_float_histogram", m: "test_float_histogram",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ // 29 { // 29
m: "test_float_histogram", m: "test_float_histogram",
@ -1481,7 +1482,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 37 { // 37
m: "test_gauge_float_histogram", m: "test_gauge_float_histogram",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, },
{ // 38 { // 38
m: "test_gauge_float_histogram", m: "test_gauge_float_histogram",
@ -1575,7 +1576,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 46 { // 46
m: "test_histogram2", m: "test_histogram2",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ // 47 { // 47
m: "test_histogram2_count", m: "test_histogram2_count",
@ -1635,7 +1636,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 54 { // 54
m: "test_histogram_family", m: "test_histogram_family",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ // 55 { // 55
m: "test_histogram_family\xfffoo\xffbar", m: "test_histogram_family\xfffoo\xffbar",
@ -1765,7 +1766,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 68 { // 68
m: "test_float_histogram_with_zerothreshold_zero", m: "test_float_histogram_with_zerothreshold_zero",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ // 69 { // 69
m: "test_float_histogram_with_zerothreshold_zero", m: "test_float_histogram_with_zerothreshold_zero",
@ -1789,7 +1790,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 71 { // 71
m: "rpc_durations_seconds", m: "rpc_durations_seconds",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, },
{ // 72 { // 72
m: "rpc_durations_seconds_count\xffservice\xffexponential", m: "rpc_durations_seconds_count\xffservice\xffexponential",
@ -1840,7 +1841,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 78 { // 78
m: "without_quantiles", m: "without_quantiles",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, },
{ // 79 { // 79
m: "without_quantiles_count", m: "without_quantiles_count",
@ -1862,7 +1863,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 79 { // 79
m: "empty_histogram", m: "empty_histogram",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ // 80 { // 80
m: "empty_histogram", m: "empty_histogram",
@ -1881,7 +1882,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 82 { // 82
m: "test_counter_with_createdtimestamp", m: "test_counter_with_createdtimestamp",
typ: MetricTypeCounter, typ: model.MetricTypeCounter,
}, },
{ // 83 { // 83
m: "test_counter_with_createdtimestamp", m: "test_counter_with_createdtimestamp",
@ -1897,7 +1898,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 85 { // 85
m: "test_summary_with_createdtimestamp", m: "test_summary_with_createdtimestamp",
typ: MetricTypeSummary, typ: model.MetricTypeSummary,
}, },
{ // 86 { // 86
m: "test_summary_with_createdtimestamp_count", m: "test_summary_with_createdtimestamp_count",
@ -1921,7 +1922,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 89 { // 89
m: "test_histogram_with_createdtimestamp", m: "test_histogram_with_createdtimestamp",
typ: MetricTypeHistogram, typ: model.MetricTypeHistogram,
}, },
{ // 90 { // 90
m: "test_histogram_with_createdtimestamp", m: "test_histogram_with_createdtimestamp",
@ -1941,7 +1942,7 @@ func TestProtobufParse(t *testing.T) {
}, },
{ // 92 { // 92
m: "test_gaugehistogram_with_createdtimestamp", m: "test_gaugehistogram_with_createdtimestamp",
typ: MetricTypeGaugeHistogram, typ: model.MetricTypeGaugeHistogram,
}, },
{ // 93 { // 93
m: "test_gaugehistogram_with_createdtimestamp", m: "test_gaugehistogram_with_createdtimestamp",

View file

@ -164,7 +164,7 @@ func (Chunk_Encoding) EnumDescriptor() ([]byte, []int) {
type MetricMetadata struct { type MetricMetadata struct {
// Represents the metric type, these match the set from Prometheus. // Represents the metric type, these match the set from Prometheus.
// Refer to model/textparse/interface.go for details. // Refer to github.com/prometheus/common/model/metadata.go for details.
Type MetricMetadata_MetricType `protobuf:"varint,1,opt,name=type,proto3,enum=prometheus.MetricMetadata_MetricType" json:"type,omitempty"` Type MetricMetadata_MetricType `protobuf:"varint,1,opt,name=type,proto3,enum=prometheus.MetricMetadata_MetricType" json:"type,omitempty"`
MetricFamilyName string `protobuf:"bytes,2,opt,name=metric_family_name,json=metricFamilyName,proto3" json:"metric_family_name,omitempty"` MetricFamilyName string `protobuf:"bytes,2,opt,name=metric_family_name,json=metricFamilyName,proto3" json:"metric_family_name,omitempty"`
Help string `protobuf:"bytes,4,opt,name=help,proto3" json:"help,omitempty"` Help string `protobuf:"bytes,4,opt,name=help,proto3" json:"help,omitempty"`

View file

@ -31,7 +31,7 @@ message MetricMetadata {
} }
// Represents the metric type, these match the set from Prometheus. // Represents the metric type, these match the set from Prometheus.
// Refer to model/textparse/interface.go for details. // Refer to github.com/prometheus/common/model/metadata.go for details.
MetricType type = 1; MetricType type = 1;
string metric_family_name = 2; string metric_family_name = 2;
string help = 4; string help = 4;

View file

@ -296,8 +296,12 @@ func BenchmarkNativeHistograms(b *testing.B) {
query: "sum(native_histogram_series)", query: "sum(native_histogram_series)",
}, },
{ {
name: "sum rate", name: "sum rate with short rate interval",
query: "sum(rate(native_histogram_series[1m]))", query: "sum(rate(native_histogram_series[2m]))",
},
{
name: "sum rate with long rate interval",
query: "sum(rate(native_histogram_series[20m]))",
}, },
} }

View file

@ -2052,7 +2052,12 @@ func (ev *evaluator) matrixIterSlice(
var drop int var drop int
for drop = 0; histograms[drop].T < mint; drop++ { for drop = 0; histograms[drop].T < mint; drop++ {
} }
// Rotate the buffer around the drop index so that points before mint can be
// reused to store new histograms.
tail := make([]HPoint, drop)
copy(tail, histograms[:drop])
copy(histograms, histograms[drop:]) copy(histograms, histograms[drop:])
copy(histograms[len(histograms)-drop:], tail)
histograms = histograms[:len(histograms)-drop] histograms = histograms[:len(histograms)-drop]
ev.currentSamples -= totalHPointSize(histograms) ev.currentSamples -= totalHPointSize(histograms)
// Only append points with timestamps after the last timestamp we have. // Only append points with timestamps after the last timestamp we have.
@ -2121,17 +2126,22 @@ loop:
// The sought sample might also be in the range. // The sought sample might also be in the range.
switch soughtValueType { switch soughtValueType {
case chunkenc.ValFloatHistogram, chunkenc.ValHistogram: case chunkenc.ValFloatHistogram, chunkenc.ValHistogram:
t, h := it.AtFloatHistogram() t := it.AtT()
if t == maxt && !value.IsStaleNaN(h.Sum) { if t == maxt {
if ev.currentSamples >= ev.maxSamples { _, h := it.AtFloatHistogram()
ev.error(ErrTooManySamples(env)) if !value.IsStaleNaN(h.Sum) {
if ev.currentSamples >= ev.maxSamples {
ev.error(ErrTooManySamples(env))
}
if histograms == nil {
histograms = getHPointSlice(16)
}
// The last sample comes directly from the iterator, so we need to copy it to
// avoid having the same reference twice in the buffer.
point := HPoint{T: t, H: h.Copy()}
histograms = append(histograms, point)
ev.currentSamples += point.size()
} }
if histograms == nil {
histograms = getHPointSlice(16)
}
point := HPoint{T: t, H: h}
histograms = append(histograms, point)
ev.currentSamples += point.size()
} }
case chunkenc.ValFloat: case chunkenc.ValFloat:
t, f := it.At() t, f := it.At()

View file

@ -18,7 +18,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"math" "math"
"os"
"sort" "sort"
"testing" "testing"
"time" "time"
@ -47,9 +46,7 @@ func TestMain(m *testing.M) {
func TestQueryConcurrency(t *testing.T) { func TestQueryConcurrency(t *testing.T) {
maxConcurrency := 10 maxConcurrency := 10
dir, err := os.MkdirTemp("", "test_concurrency") dir := t.TempDir()
require.NoError(t, err)
defer os.RemoveAll(dir)
queryTracker := NewActiveQueryTracker(dir, maxConcurrency, nil) queryTracker := NewActiveQueryTracker(dir, maxConcurrency, nil)
t.Cleanup(queryTracker.Close) t.Cleanup(queryTracker.Close)
@ -3169,28 +3166,75 @@ func TestNativeHistogramRate(t *testing.T) {
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
queryString := fmt.Sprintf("rate(%s[1m])", seriesName) queryString := fmt.Sprintf("rate(%s[45s])", seriesName)
qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(int64(5*time.Minute/time.Millisecond))) t.Run("instant_query", func(t *testing.T) {
require.NoError(t, err) qry, err := engine.NewInstantQuery(context.Background(), storage, nil, queryString, timestamp.Time(int64(5*time.Minute/time.Millisecond)))
res := qry.Exec(context.Background()) require.NoError(t, err)
require.NoError(t, res.Err) res := qry.Exec(context.Background())
vector, err := res.Vector() require.NoError(t, res.Err)
require.NoError(t, err) vector, err := res.Vector()
require.Len(t, vector, 1) require.NoError(t, err)
actualHistogram := vector[0].H require.Len(t, vector, 1)
expectedHistogram := &histogram.FloatHistogram{ actualHistogram := vector[0].H
CounterResetHint: histogram.GaugeType, expectedHistogram := &histogram.FloatHistogram{
Schema: 1, CounterResetHint: histogram.GaugeType,
ZeroThreshold: 0.001, Schema: 1,
ZeroCount: 1. / 15., ZeroThreshold: 0.001,
Count: 9. / 15., ZeroCount: 1. / 15.,
Sum: 1.226666666666667, Count: 9. / 15.,
PositiveSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}}, Sum: 1.2266666666666663,
PositiveBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.}, PositiveSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}},
NegativeSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}}, PositiveBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.},
NegativeBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.}, NegativeSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}},
} NegativeBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.},
require.Equal(t, expectedHistogram, actualHistogram) }
require.Equal(t, expectedHistogram, actualHistogram)
})
t.Run("range_query", func(t *testing.T) {
step := 30 * time.Second
start := timestamp.Time(int64(5 * time.Minute / time.Millisecond))
end := start.Add(step)
qry, err := engine.NewRangeQuery(context.Background(), storage, nil, queryString, start, end, step)
require.NoError(t, err)
res := qry.Exec(context.Background())
require.NoError(t, res.Err)
matrix, err := res.Matrix()
require.NoError(t, err)
require.Len(t, matrix, 1)
require.Len(t, matrix[0].Histograms, 2)
actualHistograms := matrix[0].Histograms
expectedHistograms := []HPoint{{
T: 300000,
H: &histogram.FloatHistogram{
CounterResetHint: histogram.GaugeType,
Schema: 1,
ZeroThreshold: 0.001,
ZeroCount: 1. / 15.,
Count: 9. / 15.,
Sum: 1.2266666666666663,
PositiveSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}},
PositiveBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.},
NegativeSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}},
NegativeBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.},
},
}, {
T: 330000,
H: &histogram.FloatHistogram{
CounterResetHint: histogram.GaugeType,
Schema: 1,
ZeroThreshold: 0.001,
ZeroCount: 1. / 15.,
Count: 9. / 15.,
Sum: 1.2266666666666663,
PositiveSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}},
PositiveBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.},
NegativeSpans: []histogram.Span{{Offset: 0, Length: 2}, {Offset: 1, Length: 2}},
NegativeBuckets: []float64{1. / 15., 1. / 15., 1. / 15., 1. / 15.},
},
}}
require.Equal(t, expectedHistograms, actualHistograms)
})
} }
func TestNativeFloatHistogramRate(t *testing.T) { func TestNativeFloatHistogramRate(t *testing.T) {

View file

@ -288,24 +288,10 @@ func (m *Manager) TargetsActive() map[string][]*Target {
m.mtxScrape.Lock() m.mtxScrape.Lock()
defer m.mtxScrape.Unlock() defer m.mtxScrape.Unlock()
var (
wg sync.WaitGroup
mtx sync.Mutex
)
targets := make(map[string][]*Target, len(m.scrapePools)) targets := make(map[string][]*Target, len(m.scrapePools))
wg.Add(len(m.scrapePools))
for tset, sp := range m.scrapePools { for tset, sp := range m.scrapePools {
// Running in parallel limits the blocking time of scrapePool to scrape targets[tset] = sp.ActiveTargets()
// interval when there's an update from SD.
go func(tset string, sp *scrapePool) {
mtx.Lock()
targets[tset] = sp.ActiveTargets()
mtx.Unlock()
wg.Done()
}(tset, sp)
} }
wg.Wait()
return targets return targets
} }

View file

@ -286,8 +286,8 @@ func (mc *MetadataMetricsCollector) Collect(ch chan<- prometheus.Metric) {
for tset, targets := range mc.TargetsGatherer.TargetsActive() { for tset, targets := range mc.TargetsGatherer.TargetsActive() {
var size, length int var size, length int
for _, t := range targets { for _, t := range targets {
size += t.MetadataSize() size += t.SizeMetadata()
length += t.MetadataLength() length += t.LengthMetadata()
} }
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View file

@ -675,7 +675,7 @@ func acceptHeader(sps []config.ScrapeProtocol) string {
weight-- weight--
} }
// Default match anything. // Default match anything.
vals = append(vals, fmt.Sprintf("*/*;q=%d", weight)) vals = append(vals, fmt.Sprintf("*/*;q=0.%d", weight))
return strings.Join(vals, ",") return strings.Join(vals, ",")
} }
@ -961,12 +961,12 @@ func (c *scrapeCache) forEachStale(f func(labels.Labels) bool) {
} }
} }
func (c *scrapeCache) setType(metric []byte, t textparse.MetricType) { func (c *scrapeCache) setType(metric []byte, t model.MetricType) {
c.metaMtx.Lock() c.metaMtx.Lock()
e, ok := c.metadata[string(metric)] e, ok := c.metadata[string(metric)]
if !ok { if !ok {
e = &metaEntry{Metadata: metadata.Metadata{Type: textparse.MetricTypeUnknown}} e = &metaEntry{Metadata: metadata.Metadata{Type: model.MetricTypeUnknown}}
c.metadata[string(metric)] = e c.metadata[string(metric)] = e
} }
if e.Type != t { if e.Type != t {
@ -983,7 +983,7 @@ func (c *scrapeCache) setHelp(metric, help []byte) {
e, ok := c.metadata[string(metric)] e, ok := c.metadata[string(metric)]
if !ok { if !ok {
e = &metaEntry{Metadata: metadata.Metadata{Type: textparse.MetricTypeUnknown}} e = &metaEntry{Metadata: metadata.Metadata{Type: model.MetricTypeUnknown}}
c.metadata[string(metric)] = e c.metadata[string(metric)] = e
} }
if e.Help != string(help) { if e.Help != string(help) {
@ -1000,7 +1000,7 @@ func (c *scrapeCache) setUnit(metric, unit []byte) {
e, ok := c.metadata[string(metric)] e, ok := c.metadata[string(metric)]
if !ok { if !ok {
e = &metaEntry{Metadata: metadata.Metadata{Type: textparse.MetricTypeUnknown}} e = &metaEntry{Metadata: metadata.Metadata{Type: model.MetricTypeUnknown}}
c.metadata[string(metric)] = e c.metadata[string(metric)] = e
} }
if e.Unit != string(unit) { if e.Unit != string(unit) {

View file

@ -971,19 +971,19 @@ test_metric 1
md, ok := cache.GetMetadata("test_metric") md, ok := cache.GetMetadata("test_metric")
require.True(t, ok, "expected metadata to be present") require.True(t, ok, "expected metadata to be present")
require.Equal(t, textparse.MetricTypeCounter, md.Type, "unexpected metric type") require.Equal(t, model.MetricTypeCounter, md.Type, "unexpected metric type")
require.Equal(t, "some help text", md.Help) require.Equal(t, "some help text", md.Help)
require.Equal(t, "metric", md.Unit) require.Equal(t, "metric", md.Unit)
md, ok = cache.GetMetadata("test_metric_no_help") md, ok = cache.GetMetadata("test_metric_no_help")
require.True(t, ok, "expected metadata to be present") require.True(t, ok, "expected metadata to be present")
require.Equal(t, textparse.MetricTypeGauge, md.Type, "unexpected metric type") require.Equal(t, model.MetricTypeGauge, md.Type, "unexpected metric type")
require.Equal(t, "", md.Help) require.Equal(t, "", md.Help)
require.Equal(t, "", md.Unit) require.Equal(t, "", md.Unit)
md, ok = cache.GetMetadata("test_metric_no_type") md, ok = cache.GetMetadata("test_metric_no_type")
require.True(t, ok, "expected metadata to be present") require.True(t, ok, "expected metadata to be present")
require.Equal(t, textparse.MetricTypeUnknown, md.Type, "unexpected metric type") require.Equal(t, model.MetricTypeUnknown, md.Type, "unexpected metric type")
require.Equal(t, "other help text", md.Help) require.Equal(t, "other help text", md.Help)
require.Equal(t, "", md.Unit) require.Equal(t, "", md.Unit)
} }

View file

@ -30,7 +30,6 @@ import (
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/relabel" "github.com/prometheus/prometheus/model/relabel"
"github.com/prometheus/prometheus/model/textparse"
"github.com/prometheus/prometheus/model/value" "github.com/prometheus/prometheus/model/value"
"github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/storage"
) )
@ -87,12 +86,12 @@ type MetricMetadataStore interface {
// MetricMetadata is a piece of metadata for a metric. // MetricMetadata is a piece of metadata for a metric.
type MetricMetadata struct { type MetricMetadata struct {
Metric string Metric string
Type textparse.MetricType Type model.MetricType
Help string Help string
Unit string Unit string
} }
func (t *Target) MetadataList() []MetricMetadata { func (t *Target) ListMetadata() []MetricMetadata {
t.mtx.RLock() t.mtx.RLock()
defer t.mtx.RUnlock() defer t.mtx.RUnlock()
@ -102,7 +101,7 @@ func (t *Target) MetadataList() []MetricMetadata {
return t.metadata.ListMetadata() return t.metadata.ListMetadata()
} }
func (t *Target) MetadataSize() int { func (t *Target) SizeMetadata() int {
t.mtx.RLock() t.mtx.RLock()
defer t.mtx.RUnlock() defer t.mtx.RUnlock()
@ -113,7 +112,7 @@ func (t *Target) MetadataSize() int {
return t.metadata.SizeMetadata() return t.metadata.SizeMetadata()
} }
func (t *Target) MetadataLength() int { func (t *Target) LengthMetadata() int {
t.mtx.RLock() t.mtx.RLock()
defer t.mtx.RUnlock() defer t.mtx.RUnlock()
@ -124,8 +123,8 @@ func (t *Target) MetadataLength() int {
return t.metadata.LengthMetadata() return t.metadata.LengthMetadata()
} }
// Metadata returns type and help metadata for the given metric. // GetMetadata returns type and help metadata for the given metric.
func (t *Target) Metadata(metric string) (MetricMetadata, bool) { func (t *Target) GetMetadata(metric string) (MetricMetadata, bool) {
t.mtx.RLock() t.mtx.RLock()
defer t.mtx.RUnlock() defer t.mtx.RUnlock()

View file

@ -12,8 +12,14 @@ on:
- ".golangci.yml" - ".golangci.yml"
pull_request: pull_request:
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
golangci: golangci:
permissions:
contents: read # for actions/checkout to fetch code
pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
name: lint name: lint
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

View file

@ -33,7 +33,6 @@ import (
"github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/textparse"
"github.com/prometheus/prometheus/prompb" "github.com/prometheus/prometheus/prompb"
writev2 "github.com/prometheus/prometheus/prompb/write/v2" writev2 "github.com/prometheus/prometheus/prompb/write/v2"
"github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/storage"
@ -915,7 +914,7 @@ func Uint32StrRefToLabels(symbols []string, minLabels []uint32) labels.Labels {
} }
// metricTypeToMetricTypeProto transforms a Prometheus metricType into prompb metricType. Since the former is a string we need to transform it to an enum. // metricTypeToMetricTypeProto transforms a Prometheus metricType into prompb metricType. Since the former is a string we need to transform it to an enum.
func metricTypeToMetricTypeProto(t textparse.MetricType) prompb.MetricMetadata_MetricType { func metricTypeToMetricTypeProto(t model.MetricType) prompb.MetricMetadata_MetricType {
mt := strings.ToUpper(string(t)) mt := strings.ToUpper(string(t))
v, ok := prompb.MetricMetadata_MetricType_value[mt] v, ok := prompb.MetricMetadata_MetricType_value[mt]
if !ok { if !ok {

View file

@ -20,11 +20,11 @@ import (
"testing" "testing"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/textparse"
"github.com/prometheus/prometheus/prompb" "github.com/prometheus/prometheus/prompb"
writev2 "github.com/prometheus/prometheus/prompb/write/v2" writev2 "github.com/prometheus/prometheus/prompb/write/v2"
"github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/storage"
@ -529,17 +529,17 @@ func TestMergeLabels(t *testing.T) {
func TestMetricTypeToMetricTypeProto(t *testing.T) { func TestMetricTypeToMetricTypeProto(t *testing.T) {
tc := []struct { tc := []struct {
desc string desc string
input textparse.MetricType input model.MetricType
expected prompb.MetricMetadata_MetricType expected prompb.MetricMetadata_MetricType
}{ }{
{ {
desc: "with a single-word metric", desc: "with a single-word metric",
input: textparse.MetricTypeCounter, input: model.MetricTypeCounter,
expected: prompb.MetricMetadata_COUNTER, expected: prompb.MetricMetadata_COUNTER,
}, },
{ {
desc: "with a two-word metric", desc: "with a two-word metric",
input: textparse.MetricTypeStateset, input: model.MetricTypeStateset,
expected: prompb.MetricMetadata_STATESET, expected: prompb.MetricMetadata_STATESET,
}, },
{ {

View file

@ -136,7 +136,7 @@ func (mw *MetadataWatcher) collect() {
metadata := []scrape.MetricMetadata{} metadata := []scrape.MetricMetadata{}
for _, tset := range mw.manager.TargetsActive() { for _, tset := range mw.manager.TargetsActive() {
for _, target := range tset { for _, target := range tset {
for _, entry := range target.MetadataList() { for _, entry := range target.ListMetadata() {
if _, ok := metadataSet[entry]; !ok { if _, ok := metadataSet[entry]; !ok {
metadata = append(metadata, entry) metadata = append(metadata, entry)
metadataSet[entry] = struct{}{} metadataSet[entry] = struct{}{}

View file

@ -22,7 +22,6 @@ import (
"github.com/prometheus/common/model" "github.com/prometheus/common/model"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/textparse"
"github.com/prometheus/prometheus/scrape" "github.com/prometheus/prometheus/scrape"
) )
@ -108,13 +107,13 @@ func TestWatchScrapeManager_ReadyForCollection(t *testing.T) {
Metadata: []scrape.MetricMetadata{ Metadata: []scrape.MetricMetadata{
{ {
Metric: "prometheus_tsdb_head_chunks_created_total", Metric: "prometheus_tsdb_head_chunks_created_total",
Type: textparse.MetricTypeCounter, Type: model.MetricTypeCounter,
Help: "Total number", Help: "Total number",
Unit: "", Unit: "",
}, },
{ {
Metric: "prometheus_remote_storage_retried_samples_total", Metric: "prometheus_remote_storage_retried_samples_total",
Type: textparse.MetricTypeCounter, Type: model.MetricTypeCounter,
Help: "Total number", Help: "Total number",
Unit: "", Unit: "",
}, },
@ -124,7 +123,7 @@ func TestWatchScrapeManager_ReadyForCollection(t *testing.T) {
Metadata: []scrape.MetricMetadata{ Metadata: []scrape.MetricMetadata{
{ {
Metric: "prometheus_tsdb_head_chunks_created_total", Metric: "prometheus_tsdb_head_chunks_created_total",
Type: textparse.MetricTypeCounter, Type: model.MetricTypeCounter,
Help: "Total number", Help: "Total number",
Unit: "", Unit: "",
}, },

View file

@ -39,7 +39,6 @@ import (
"github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/textparse"
"github.com/prometheus/prometheus/model/timestamp" "github.com/prometheus/prometheus/model/timestamp"
"github.com/prometheus/prometheus/prompb" "github.com/prometheus/prometheus/prompb"
writev2 "github.com/prometheus/prometheus/prompb/write/v2" writev2 "github.com/prometheus/prometheus/prompb/write/v2"
@ -188,7 +187,7 @@ func TestMetadataDelivery(t *testing.T) {
for i := 0; i < numMetadata; i++ { for i := 0; i < numMetadata; i++ {
metadata = append(metadata, scrape.MetricMetadata{ metadata = append(metadata, scrape.MetricMetadata{
Metric: "prometheus_remote_storage_sent_metadata_bytes_total_" + strconv.Itoa(i), Metric: "prometheus_remote_storage_sent_metadata_bytes_total_" + strconv.Itoa(i),
Type: textparse.MetricTypeCounter, Type: model.MetricTypeCounter,
Help: "a nice help text", Help: "a nice help text",
Unit: "", Unit: "",
}) })

View file

@ -1038,7 +1038,7 @@ func (a *headAppender) Commit() (err error) {
for i, m := range a.metadata { for i, m := range a.metadata {
series = a.metadataSeries[i] series = a.metadataSeries[i]
series.Lock() series.Lock()
series.meta = &metadata.Metadata{Type: record.ToTextparseMetricType(m.Type), Unit: m.Unit, Help: m.Help} series.meta = &metadata.Metadata{Type: record.ToMetricType(m.Type), Unit: m.Unit, Help: m.Help}
series.Unlock() series.Unlock()
} }

View file

@ -388,7 +388,7 @@ Outer:
continue continue
} }
s.meta = &metadata.Metadata{ s.meta = &metadata.Metadata{
Type: record.ToTextparseMetricType(m.Type), Type: record.ToMetricType(m.Type),
Unit: m.Unit, Unit: m.Unit,
Help: m.Help, Help: m.Help,
} }

View file

@ -20,9 +20,10 @@ import (
"fmt" "fmt"
"math" "math"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/histogram"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/textparse"
"github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/tsdb/chunks" "github.com/prometheus/prometheus/tsdb/chunks"
"github.com/prometheus/prometheus/tsdb/encoding" "github.com/prometheus/prometheus/tsdb/encoding"
@ -90,45 +91,45 @@ const (
Stateset MetricType = 7 Stateset MetricType = 7
) )
func GetMetricType(t textparse.MetricType) uint8 { func GetMetricType(t model.MetricType) uint8 {
switch t { switch t {
case textparse.MetricTypeCounter: case model.MetricTypeCounter:
return uint8(Counter) return uint8(Counter)
case textparse.MetricTypeGauge: case model.MetricTypeGauge:
return uint8(Gauge) return uint8(Gauge)
case textparse.MetricTypeHistogram: case model.MetricTypeHistogram:
return uint8(HistogramSample) return uint8(HistogramSample)
case textparse.MetricTypeGaugeHistogram: case model.MetricTypeGaugeHistogram:
return uint8(GaugeHistogram) return uint8(GaugeHistogram)
case textparse.MetricTypeSummary: case model.MetricTypeSummary:
return uint8(Summary) return uint8(Summary)
case textparse.MetricTypeInfo: case model.MetricTypeInfo:
return uint8(Info) return uint8(Info)
case textparse.MetricTypeStateset: case model.MetricTypeStateset:
return uint8(Stateset) return uint8(Stateset)
default: default:
return uint8(UnknownMT) return uint8(UnknownMT)
} }
} }
func ToTextparseMetricType(m uint8) textparse.MetricType { func ToMetricType(m uint8) model.MetricType {
switch m { switch m {
case uint8(Counter): case uint8(Counter):
return textparse.MetricTypeCounter return model.MetricTypeCounter
case uint8(Gauge): case uint8(Gauge):
return textparse.MetricTypeGauge return model.MetricTypeGauge
case uint8(HistogramSample): case uint8(HistogramSample):
return textparse.MetricTypeHistogram return model.MetricTypeHistogram
case uint8(GaugeHistogram): case uint8(GaugeHistogram):
return textparse.MetricTypeGaugeHistogram return model.MetricTypeGaugeHistogram
case uint8(Summary): case uint8(Summary):
return textparse.MetricTypeSummary return model.MetricTypeSummary
case uint8(Info): case uint8(Info):
return textparse.MetricTypeInfo return model.MetricTypeInfo
case uint8(Stateset): case uint8(Stateset):
return textparse.MetricTypeStateset return model.MetricTypeStateset
default: default:
return textparse.MetricTypeUnknown return model.MetricTypeUnknown
} }
} }

View file

@ -60,11 +60,7 @@ func TestDirLockerUsage(t *testing.T, open func(t *testing.T, data string, creat
for _, c := range cases { for _, c := range cases {
t.Run(fmt.Sprintf("%+v", c), func(t *testing.T) { t.Run(fmt.Sprintf("%+v", c), func(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "test") tmpdir := t.TempDir()
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, os.RemoveAll(tmpdir))
})
// Test preconditions (file already exists + lockfile option) // Test preconditions (file already exists + lockfile option)
if c.fileAlreadyExists { if c.fileAlreadyExists {
@ -82,7 +78,7 @@ func TestDirLockerUsage(t *testing.T, open func(t *testing.T, data string, creat
// Check that the lockfile is always deleted // Check that the lockfile is always deleted
if !c.lockFileDisabled { if !c.lockFileDisabled {
_, err = os.Stat(locker.path) _, err := os.Stat(locker.path)
require.True(t, os.IsNotExist(err), "lockfile was not deleted") require.True(t, os.IsNotExist(err), "lockfile was not deleted")
} }
}) })

View file

@ -30,6 +30,14 @@ func GenerateTestHistograms(n int) (r []*histogram.Histogram) {
return r return r
} }
func GenerateTestHistogramsWithUnknownResetHint(n int) []*histogram.Histogram {
hs := GenerateTestHistograms(n)
for i := range hs {
hs[i].CounterResetHint = histogram.UnknownCounterReset
}
return hs
}
// GenerateTestHistogram but it is up to the user to set any known counter reset hint. // GenerateTestHistogram but it is up to the user to set any known counter reset hint.
func GenerateTestHistogram(i int) *histogram.Histogram { func GenerateTestHistogram(i int) *histogram.Histogram {
return &histogram.Histogram{ return &histogram.Histogram{

View file

@ -41,7 +41,7 @@ import (
"github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/textparse" "github.com/prometheus/prometheus/model/metadata"
"github.com/prometheus/prometheus/model/timestamp" "github.com/prometheus/prometheus/model/timestamp"
"github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/promql/parser"
@ -1115,7 +1115,7 @@ func (api *API) targetMetadata(r *http.Request) apiFuncResult {
} }
// If no metric is specified, get the full list for the target. // If no metric is specified, get the full list for the target.
if metric == "" { if metric == "" {
for _, md := range t.MetadataList() { for _, md := range t.ListMetadata() {
res = append(res, metricMetadata{ res = append(res, metricMetadata{
Target: t.Labels(), Target: t.Labels(),
Metric: md.Metric, Metric: md.Metric,
@ -1127,7 +1127,7 @@ func (api *API) targetMetadata(r *http.Request) apiFuncResult {
continue continue
} }
// Get metadata for the specified metric. // Get metadata for the specified metric.
if md, ok := t.Metadata(metric); ok { if md, ok := t.GetMetadata(metric); ok {
res = append(res, metricMetadata{ res = append(res, metricMetadata{
Target: t.Labels(), Target: t.Labels(),
Type: md.Type, Type: md.Type,
@ -1142,11 +1142,11 @@ func (api *API) targetMetadata(r *http.Request) apiFuncResult {
} }
type metricMetadata struct { type metricMetadata struct {
Target labels.Labels `json:"target"` Target labels.Labels `json:"target"`
Metric string `json:"metric,omitempty"` Metric string `json:"metric,omitempty"`
Type textparse.MetricType `json:"type"` Type model.MetricType `json:"type"`
Help string `json:"help"` Help string `json:"help"`
Unit string `json:"unit"` Unit string `json:"unit"`
} }
// AlertmanagerDiscovery has all the active Alertmanagers. // AlertmanagerDiscovery has all the active Alertmanagers.
@ -1222,14 +1222,8 @@ func rulesAlertsToAPIAlerts(rulesAlerts []*rules.Alert) []*Alert {
return apiAlerts return apiAlerts
} }
type metadata struct {
Type textparse.MetricType `json:"type"`
Help string `json:"help"`
Unit string `json:"unit"`
}
func (api *API) metricMetadata(r *http.Request) apiFuncResult { func (api *API) metricMetadata(r *http.Request) apiFuncResult {
metrics := map[string]map[metadata]struct{}{} metrics := map[string]map[metadata.Metadata]struct{}{}
limit := -1 limit := -1
if s := r.FormValue("limit"); s != "" { if s := r.FormValue("limit"); s != "" {
@ -1250,8 +1244,8 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
for _, tt := range api.targetRetriever(r.Context()).TargetsActive() { for _, tt := range api.targetRetriever(r.Context()).TargetsActive() {
for _, t := range tt { for _, t := range tt {
if metric == "" { if metric == "" {
for _, mm := range t.MetadataList() { for _, mm := range t.ListMetadata() {
m := metadata{Type: mm.Type, Help: mm.Help, Unit: mm.Unit} m := metadata.Metadata{Type: mm.Type, Help: mm.Help, Unit: mm.Unit}
ms, ok := metrics[mm.Metric] ms, ok := metrics[mm.Metric]
if limitPerMetric > 0 && len(ms) >= limitPerMetric { if limitPerMetric > 0 && len(ms) >= limitPerMetric {
@ -1259,7 +1253,7 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
} }
if !ok { if !ok {
ms = map[metadata]struct{}{} ms = map[metadata.Metadata]struct{}{}
metrics[mm.Metric] = ms metrics[mm.Metric] = ms
} }
ms[m] = struct{}{} ms[m] = struct{}{}
@ -1267,8 +1261,8 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
continue continue
} }
if md, ok := t.Metadata(metric); ok { if md, ok := t.GetMetadata(metric); ok {
m := metadata{Type: md.Type, Help: md.Help, Unit: md.Unit} m := metadata.Metadata{Type: md.Type, Help: md.Help, Unit: md.Unit}
ms, ok := metrics[md.Metric] ms, ok := metrics[md.Metric]
if limitPerMetric > 0 && len(ms) >= limitPerMetric { if limitPerMetric > 0 && len(ms) >= limitPerMetric {
@ -1276,7 +1270,7 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
} }
if !ok { if !ok {
ms = map[metadata]struct{}{} ms = map[metadata.Metadata]struct{}{}
metrics[md.Metric] = ms metrics[md.Metric] = ms
} }
ms[m] = struct{}{} ms[m] = struct{}{}
@ -1285,13 +1279,13 @@ func (api *API) metricMetadata(r *http.Request) apiFuncResult {
} }
// Put the elements from the pseudo-set into a slice for marshaling. // Put the elements from the pseudo-set into a slice for marshaling.
res := map[string][]metadata{} res := map[string][]metadata.Metadata{}
for name, set := range metrics { for name, set := range metrics {
if limit >= 0 && len(res) >= limit { if limit >= 0 && len(res) >= limit {
break break
} }
s := []metadata{} s := []metadata.Metadata{}
for metadata := range set { for metadata := range set {
s = append(s, metadata) s = append(s, metadata)
} }

View file

@ -44,7 +44,7 @@ import (
"github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/exemplar"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/textparse" "github.com/prometheus/prometheus/model/metadata"
"github.com/prometheus/prometheus/model/timestamp" "github.com/prometheus/prometheus/model/timestamp"
"github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/promql/parser"
@ -1585,7 +1585,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created.", Help: "Number of OS threads created.",
Unit: "", Unit: "",
}, },
@ -1598,7 +1598,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
"job": "test", "job": "test",
}), }),
Help: "Number of OS threads created.", Help: "Number of OS threads created.",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Unit: "", Unit: "",
}, },
}, },
@ -1615,7 +1615,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "prometheus_tsdb_storage_blocks_bytes", Metric: "prometheus_tsdb_storage_blocks_bytes",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "The number of bytes that are currently used for local storage by all blocks.", Help: "The number of bytes that are currently used for local storage by all blocks.",
Unit: "", Unit: "",
}, },
@ -1629,7 +1629,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
}), }),
Metric: "prometheus_tsdb_storage_blocks_bytes", Metric: "prometheus_tsdb_storage_blocks_bytes",
Help: "The number of bytes that are currently used for local storage by all blocks.", Help: "The number of bytes that are currently used for local storage by all blocks.",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Unit: "", Unit: "",
}, },
}, },
@ -1643,7 +1643,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created.", Help: "Number of OS threads created.",
Unit: "", Unit: "",
}, },
@ -1654,7 +1654,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "prometheus_tsdb_storage_blocks_bytes", Metric: "prometheus_tsdb_storage_blocks_bytes",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "The number of bytes that are currently used for local storage by all blocks.", Help: "The number of bytes that are currently used for local storage by all blocks.",
Unit: "", Unit: "",
}, },
@ -1668,7 +1668,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
}), }),
Metric: "go_threads", Metric: "go_threads",
Help: "Number of OS threads created.", Help: "Number of OS threads created.",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Unit: "", Unit: "",
}, },
{ {
@ -1677,7 +1677,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
}), }),
Metric: "prometheus_tsdb_storage_blocks_bytes", Metric: "prometheus_tsdb_storage_blocks_bytes",
Help: "The number of bytes that are currently used for local storage by all blocks.", Help: "The number of bytes that are currently used for local storage by all blocks.",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Unit: "", Unit: "",
}, },
}, },
@ -1720,22 +1720,22 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "prometheus_engine_query_duration_seconds", Metric: "prometheus_engine_query_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "Query timings", Help: "Query timings",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_info", Metric: "go_info",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Information about the Go environment.", Help: "Information about the Go environment.",
Unit: "", Unit: "",
}, },
}, },
}, },
}, },
response: map[string][]metadata{ response: map[string][]metadata.Metadata{
"prometheus_engine_query_duration_seconds": {{textparse.MetricTypeSummary, "Query timings", ""}}, "prometheus_engine_query_duration_seconds": {{Type: model.MetricTypeSummary, Help: "Query timings", Unit: ""}},
"go_info": {{textparse.MetricTypeGauge, "Information about the Go environment.", ""}}, "go_info": {{Type: model.MetricTypeGauge, Help: "Information about the Go environment.", Unit: ""}},
}, },
}, },
// With duplicate metadata for a metric that comes from different targets. // With duplicate metadata for a metric that comes from different targets.
@ -1747,7 +1747,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
@ -1758,15 +1758,15 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
}, },
}, },
}, },
response: map[string][]metadata{ response: map[string][]metadata.Metadata{
"go_threads": {{textparse.MetricTypeGauge, "Number of OS threads created", ""}}, "go_threads": {{Type: model.MetricTypeGauge, Help: "Number of OS threads created"}},
}, },
}, },
// With non-duplicate metadata for the same metric from different targets. // With non-duplicate metadata for the same metric from different targets.
@ -1778,7 +1778,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
@ -1789,21 +1789,21 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads that were created.", Help: "Number of OS threads that were created.",
Unit: "", Unit: "",
}, },
}, },
}, },
}, },
response: map[string][]metadata{ response: map[string][]metadata.Metadata{
"go_threads": { "go_threads": {
{textparse.MetricTypeGauge, "Number of OS threads created", ""}, {Type: model.MetricTypeGauge, Help: "Number of OS threads created"},
{textparse.MetricTypeGauge, "Number of OS threads that were created.", ""}, {Type: model.MetricTypeGauge, Help: "Number of OS threads that were created."},
}, },
}, },
sorter: func(m interface{}) { sorter: func(m interface{}) {
v := m.(map[string][]metadata)["go_threads"] v := m.(map[string][]metadata.Metadata)["go_threads"]
sort.Slice(v, func(i, j int) bool { sort.Slice(v, func(i, j int) bool {
return v[i].Help < v[j].Help return v[i].Help < v[j].Help
@ -1822,13 +1822,13 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
{ {
Metric: "prometheus_engine_query_duration_seconds", Metric: "prometheus_engine_query_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "Query Timmings.", Help: "Query Timmings.",
Unit: "", Unit: "",
}, },
@ -1839,7 +1839,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_gc_duration_seconds", Metric: "go_gc_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "A summary of the GC invocation durations.", Help: "A summary of the GC invocation durations.",
Unit: "", Unit: "",
}, },
@ -1858,31 +1858,31 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Repeated metadata", Help: "Repeated metadata",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_gc_duration_seconds", Metric: "go_gc_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "A summary of the GC invocation durations.", Help: "A summary of the GC invocation durations.",
Unit: "", Unit: "",
}, },
}, },
}, },
}, },
response: map[string][]metadata{ response: map[string][]metadata.Metadata{
"go_threads": { "go_threads": {
{textparse.MetricTypeGauge, "Number of OS threads created", ""}, {Type: model.MetricTypeGauge, Help: "Number of OS threads created"},
}, },
"go_gc_duration_seconds": { "go_gc_duration_seconds": {
{textparse.MetricTypeSummary, "A summary of the GC invocation durations.", ""}, {Type: model.MetricTypeSummary, Help: "A summary of the GC invocation durations."},
}, },
}, },
}, },
@ -1896,19 +1896,19 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Repeated metadata", Help: "Repeated metadata",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_gc_duration_seconds", Metric: "go_gc_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "A summary of the GC invocation durations.", Help: "A summary of the GC invocation durations.",
Unit: "", Unit: "",
}, },
@ -1929,19 +1929,19 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Repeated metadata", Help: "Repeated metadata",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_gc_duration_seconds", Metric: "go_gc_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "A summary of the GC invocation durations.", Help: "A summary of the GC invocation durations.",
Unit: "", Unit: "",
}, },
@ -1952,13 +1952,13 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created, but from a different target", Help: "Number of OS threads created, but from a different target",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_gc_duration_seconds", Metric: "go_gc_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "A summary of the GC invocation durations, but from a different target.", Help: "A summary of the GC invocation durations, but from a different target.",
Unit: "", Unit: "",
}, },
@ -1978,7 +1978,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
@ -1989,27 +1989,27 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_gc_duration_seconds", Metric: "go_gc_duration_seconds",
Type: textparse.MetricTypeSummary, Type: model.MetricTypeSummary,
Help: "A summary of the GC invocation durations.", Help: "A summary of the GC invocation durations.",
Unit: "", Unit: "",
}, },
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads that were created.", Help: "Number of OS threads that were created.",
Unit: "", Unit: "",
}, },
}, },
}, },
}, },
response: map[string][]metadata{ response: map[string][]metadata.Metadata{
"go_threads": { "go_threads": {
{textparse.MetricTypeGauge, "Number of OS threads created", ""}, {Type: model.MetricTypeGauge, Help: "Number of OS threads created"},
{textparse.MetricTypeGauge, "Number of OS threads that were created.", ""}, {Type: model.MetricTypeGauge, Help: "Number of OS threads that were created."},
}, },
}, },
sorter: func(m interface{}) { sorter: func(m interface{}) {
v := m.(map[string][]metadata)["go_threads"] v := m.(map[string][]metadata.Metadata)["go_threads"]
sort.Slice(v, func(i, j int) bool { sort.Slice(v, func(i, j int) bool {
return v[i].Help < v[j].Help return v[i].Help < v[j].Help
@ -2026,19 +2026,19 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata: []scrape.MetricMetadata{ metadata: []scrape.MetricMetadata{
{ {
Metric: "go_threads", Metric: "go_threads",
Type: textparse.MetricTypeGauge, Type: model.MetricTypeGauge,
Help: "Number of OS threads created", Help: "Number of OS threads created",
Unit: "", Unit: "",
}, },
}, },
}, },
}, },
response: map[string][]metadata{}, response: map[string][]metadata.Metadata{},
}, },
// With no available metadata. // With no available metadata.
{ {
endpoint: api.metricMetadata, endpoint: api.metricMetadata,
response: map[string][]metadata{}, response: map[string][]metadata.Metadata{},
}, },
{ {
endpoint: api.serveConfig, endpoint: api.serveConfig,
@ -2932,7 +2932,7 @@ func assertAPIResponseMetadataLen(t *testing.T, got interface{}, expLen int) {
t.Helper() t.Helper()
var gotLen int var gotLen int
response := got.(map[string][]metadata) response := got.(map[string][]metadata.Metadata)
for _, m := range response { for _, m := range response {
gotLen += len(m) gotLen += len(m)
} }