Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log critical consensus values during health checks #2609

Merged
merged 2 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion snow/engine/common/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@

package common

import "github.com/ava-labs/avalanchego/ids"
import (
"fmt"

"github.com/ava-labs/avalanchego/ids"
)

type Request struct {
NodeID ids.NodeID
RequestID uint32
}

func (r Request) MarshalText() ([]byte, error) {
return []byte(fmt.Sprintf("%s:%d", r.NodeID, r.RequestID)), nil
}
24 changes: 24 additions & 0 deletions snow/engine/common/request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package common

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"

"github.com/ava-labs/avalanchego/ids"
)

func TestRequestJSONMarshal(t *testing.T) {
requestMap := map[Request]ids.ID{
{
NodeID: ids.GenerateTestNodeID(),
RequestID: 12345,
}: ids.GenerateTestID(),
}
_, err := json.Marshal(requestMap)
require.NoError(t, err)
}
9 changes: 9 additions & 0 deletions snow/engine/snowman/transitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,15 @@ func (t *Transitive) HealthCheck(ctx context.Context) (interface{}, error) {
t.Ctx.Lock.Lock()
defer t.Ctx.Lock.Unlock()

t.Ctx.Log.Verbo("running health check",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

zap.Uint32("requestID", t.requestID),
zap.Int("gossipCounter", t.gossipCounter),
zap.Stringer("polls", t.polls),
zap.Reflect("outstandingBlockRequests", t.blkReqs),
zap.Stringer("blockedJobs", &t.blocked),
zap.Int("pendingBuildBlocks", t.pendingBuildBlocks),
)

consensusIntf, consensusErr := t.Consensus.HealthCheck(ctx)
vmIntf, vmErr := t.VM.HealthCheck(ctx)
intf := map[string]interface{}{
Expand Down
41 changes: 40 additions & 1 deletion utils/bimap/bimap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@

package bimap

import "github.com/ava-labs/avalanchego/utils"
import (
"bytes"
"encoding/json"
"errors"

"github.com/ava-labs/avalanchego/utils"
)

var (
_ json.Marshaler = (*BiMap[int, int])(nil)
_ json.Unmarshaler = (*BiMap[int, int])(nil)

nullBytes = []byte("null")
errNotBijective = errors.New("map not bijective")
)

type Entry[K, V any] struct {
Key K
Expand Down Expand Up @@ -100,3 +114,28 @@ func (m *BiMap[K, V]) DeleteValue(val V) (K, bool) {
func (m *BiMap[K, V]) Len() int {
return len(m.keyToValue)
}

func (m *BiMap[K, V]) MarshalJSON() ([]byte, error) {
return json.Marshal(m.keyToValue)
}

func (m *BiMap[K, V]) UnmarshalJSON(b []byte) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the custom unmarshaller used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or is this just moreso ensuring if we add marshal, we should also have unmarshal?

Copy link
Contributor Author

@StephenButtolph StephenButtolph Jan 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't used. I can remove it if you'd prefer not to have it. Although I felt like implementing json marshal on a normal data structure and not supporting unmarshaling was a bit weird.

if bytes.Equal(b, nullBytes) {
return nil
}
var keyToValue map[K]V
if err := json.Unmarshal(b, &keyToValue); err != nil {
return err
}
valueToKey := make(map[V]K, len(keyToValue))
for k, v := range keyToValue {
valueToKey[v] = k
}
if len(keyToValue) != len(valueToKey) {
return errNotBijective
}

m.keyToValue = keyToValue
m.valueToKey = valueToKey
return nil
}
28 changes: 28 additions & 0 deletions utils/bimap/bimap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package bimap

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -326,3 +327,30 @@ func TestBiMapLen(t *testing.T) {
m.DeleteKey(1)
require.Zero(m.Len())
}

func TestBiMapJSON(t *testing.T) {
require := require.New(t)

expectedMap := New[int, int]()
expectedMap.Put(1, 2)
expectedMap.Put(2, 3)

jsonBytes, err := json.Marshal(expectedMap)
require.NoError(err)

expectedJSONBytes := []byte(`{"1":2,"2":3}`)
require.Equal(expectedJSONBytes, jsonBytes)

var unmarshalledMap BiMap[int, int]
require.NoError(json.Unmarshal(jsonBytes, &unmarshalledMap))
require.Equal(expectedMap, &unmarshalledMap)
}

func TestBiMapInvalidJSON(t *testing.T) {
require := require.New(t)

invalidJSONBytes := []byte(`{"1":2,"2":2}`)
var unmarshalledMap BiMap[int, int]
err := json.Unmarshal(invalidJSONBytes, &unmarshalledMap)
require.ErrorIs(err, errNotBijective)
}
Loading