Skip to content

Commit

Permalink
Replace all chain namespaces with labels (#3053)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenButtolph authored Jun 6, 2024
1 parent 783fdfc commit 7dca396
Show file tree
Hide file tree
Showing 46 changed files with 759 additions and 436 deletions.
38 changes: 30 additions & 8 deletions api/metrics/prefix_gatherer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
package metrics

import (
"errors"
"fmt"
"slices"

"github.com/prometheus/client_golang/prometheus"
"google.golang.org/protobuf/proto"
Expand All @@ -15,7 +15,11 @@ import (
dto "github.com/prometheus/client_model/go"
)

var _ MultiGatherer = (*prefixGatherer)(nil)
var (
_ MultiGatherer = (*prefixGatherer)(nil)

errOverlappingNamespaces = errors.New("prefix could create overlapping namespaces")
)

// NewPrefixGatherer returns a new MultiGatherer that merges metrics by adding a
// prefix to their names.
Expand All @@ -31,12 +35,14 @@ func (g *prefixGatherer) Register(prefix string, gatherer prometheus.Gatherer) e
g.lock.Lock()
defer g.lock.Unlock()

// TODO: Restrict prefixes to avoid potential conflicts
if slices.Contains(g.names, prefix) {
return fmt.Errorf("%w: %q",
errDuplicateGatherer,
prefix,
)
for _, existingPrefix := range g.names {
if eitherIsPrefix(prefix, existingPrefix) {
return fmt.Errorf("%w: %q conflicts with %q",
errOverlappingNamespaces,
prefix,
existingPrefix,
)
}
}

g.names = append(g.names, prefix)
Expand Down Expand Up @@ -64,3 +70,19 @@ func (g *prefixedGatherer) Gather() ([]*dto.MetricFamily, error) {
}
return metricFamilies, err
}

// eitherIsPrefix returns true if either [a] is a prefix of [b] or [b] is a
// prefix of [a].
//
// This function accounts for the usage of the namespace boundary, so "hello" is
// not considered a prefix of "helloworld". However, "hello" is considered a
// prefix of "hello_world".
func eitherIsPrefix(a, b string) bool {
if len(a) > len(b) {
a, b = b, a
}
return a == b[:len(a)] && // a is a prefix of b
(len(a) == 0 || // a is empty
len(a) == len(b) || // a is equal to b
b[len(a)] == metric.NamespaceSeparatorByte) // a ends at a namespace boundary of b
}
56 changes: 55 additions & 1 deletion api/metrics/prefix_gatherer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func TestPrefixGatherer_Register(t *testing.T) {
prefixGatherer: firstPrefixGatherer(),
prefix: firstPrefixedGatherer.prefix,
gatherer: secondPrefixedGatherer.gatherer,
expectedErr: errDuplicateGatherer,
expectedErr: errOverlappingNamespaces,
expectedPrefixGatherer: firstPrefixGatherer(),
},
}
Expand All @@ -148,3 +148,57 @@ func TestPrefixGatherer_Register(t *testing.T) {
})
}
}

func TestEitherIsPrefix(t *testing.T) {
tests := []struct {
name string
a string
b string
expected bool
}{
{
name: "empty strings",
a: "",
b: "",
expected: true,
},
{
name: "an empty string",
a: "",
b: "hello",
expected: true,
},
{
name: "same strings",
a: "x",
b: "x",
expected: true,
},
{
name: "different strings",
a: "x",
b: "y",
expected: false,
},
{
name: "splits namespace",
a: "hello",
b: "hello_world",
expected: true,
},
{
name: "is prefix before separator",
a: "hello",
b: "helloworld",
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
require := require.New(t)

require.Equal(test.expected, eitherIsPrefix(test.a, test.b))
require.Equal(test.expected, eitherIsPrefix(test.b, test.a))
})
}
}
3 changes: 0 additions & 3 deletions chains/linearizable_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package chains
import (
"context"

"github.com/ava-labs/avalanchego/api/metrics"
"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow"
Expand All @@ -29,7 +28,6 @@ type initializeOnLinearizeVM struct {
vmToInitialize common.VM
vmToLinearize *linearizeOnInitializeVM

registerer metrics.MultiGatherer
ctx *snow.Context
db database.Database
genesisBytes []byte
Expand All @@ -42,7 +40,6 @@ type initializeOnLinearizeVM struct {

func (vm *initializeOnLinearizeVM) Linearize(ctx context.Context, stopVertexID ids.ID) error {
vm.vmToLinearize.stopVertexID = stopVertexID
vm.ctx.Metrics = vm.registerer
return vm.vmToInitialize.Initialize(
ctx,
vm.ctx,
Expand Down
Loading

0 comments on commit 7dca396

Please sign in to comment.