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

[Merged by Bors] - 4783 poet client logging #4988

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,4 @@ Doesn't affect direct peers. In order to disable:
* [#4882](https://github.com/spacemeshos/go-spacemesh/pull/4882) Increase cache size and parametrize datastore.
* [#4887](https://github.com/spacemeshos/go-spacemesh/pull/4887) Fixed crashes on API call.
* [#4871](https://github.com/spacemeshos/go-spacemesh/pull/4871) Add jitter to spread out requests to get poet proof and submit challenge
* [#4988](https://github.com/spacemeshos/go-spacemesh/pull/4988) Improve logging around communication with PoET services
2 changes: 1 addition & 1 deletion activation/nipost.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func NewNIPostBuilder(
) (*NIPostBuilder, error) {
poetClients := make(map[string]PoetProvingServiceClient, len(poetServers))
for _, address := range poetServers {
client, err := NewHTTPPoetClient(address, poetCfg)
client, err := NewHTTPPoetClient(address, poetCfg, WithLogger(lg.Zap().Named("poet")))
if err != nil {
return nil, fmt.Errorf("cannot create poet client: %w", err)
}
Expand Down
31 changes: 15 additions & 16 deletions activation/nipost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import (
"time"

"github.com/spacemeshos/go-scale/tester"
"github.com/spacemeshos/poet/logging"
"github.com/spacemeshos/post/proving"
"github.com/spacemeshos/post/verifying"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest"
"golang.org/x/sync/errgroup"

"github.com/spacemeshos/go-spacemesh/common/types"
Expand Down Expand Up @@ -167,24 +169,24 @@ func TestNIPostBuilderWithClients(t *testing.T) {
require.NoError(t, err)
}

func spawnPoet(tb testing.TB, clientCfg PoetConfig, opts ...HTTPPoetOpt) *HTTPPoetClient {
func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness {
tb.Helper()
poetProver, err := NewHTTPPoetTestHarness(context.Background(), tb.TempDir(), clientCfg, opts...)
ctx, cancel := context.WithCancel(logging.NewContext(context.Background(), zaptest.NewLogger(tb)))

poetProver, err := NewHTTPPoetTestHarness(ctx, tb.TempDir(), opts...)
require.NoError(tb, err)
require.NotNil(tb, poetProver)

var eg errgroup.Group
ctx, cancel := context.WithCancel(context.Background())
tb.Cleanup(func() {
cancel()
assert.NoError(tb, eg.Wait())
eg.Wait()
})
eg.Go(func() error {
return poetProver.Service.Start(ctx)
})
_, err = poetProver.HTTPPoetClient.PoetServiceID(context.Background())
require.NoError(tb, err)
return poetProver.HTTPPoetClient

return poetProver
}

func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge types.NIPostChallenge, poetDb poetDbAPI, validator nipostValidator) *types.NIPost {
Expand All @@ -201,22 +203,21 @@ func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge t
MaxRequestRetries: 10,
}

poetProver := spawnPoet(tb, poetCfg, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap))
poetProver := spawnPoet(tb, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap))

signer, err := signing.NewEdSigner()
require.NoError(tb, err)
nb, err := NewNIPostBuilder(
postProvider.id,
postProvider,
poetDb,
[]string{},
[]string{poetProver.RestURL().String()},
tb.TempDir(),
logtest.New(tb),
signer,
poetCfg,
mclock,
WithNipostValidator(validator),
withPoetClients([]PoetProvingServiceClient{poetProver}),
)
require.NoError(tb, err)
nipost, err := nb.BuildNIPost(context.Background(), &nipostChallenge)
Expand Down Expand Up @@ -249,7 +250,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) {
}

genesis := time.Now()
poetProver := spawnPoet(t, poetCfg, WithGenesis(genesis), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap))
poetProver := spawnPoet(t, WithGenesis(genesis), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap))

ctrl := gomock.NewController(t)
poetDb := NewMockpoetDbAPI(ctrl)
Expand All @@ -266,14 +267,13 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) {
postProvider.id,
postProvider,
poetDb,
[]string{},
[]string{poetProver.RestURL().String()},
t.TempDir(),
logtest.New(t),
postProvider.signer,
poetCfg,
mclock,
WithNipostValidator(nipostValidator),
withPoetClients([]PoetProvingServiceClient{poetProver}),
)
require.NoError(t, err)

Expand Down Expand Up @@ -593,7 +593,7 @@ func TestNIPostBuilder_Close(t *testing.T) {
ctrl := gomock.NewController(t)
postProvider := NewMockpostSetupProvider(ctrl)
postProvider.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete})
poetProver := spawnPoet(t, DefaultPoetConfig(), WithGenesis(time.Now()), WithEpochDuration(time.Second))
poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(time.Second))
poetDb := NewMockpoetDbAPI(ctrl)
challenge := types.NIPostChallenge{
PublishEpoch: postGenesisEpoch + 2,
Expand All @@ -606,13 +606,12 @@ func TestNIPostBuilder_Close(t *testing.T) {
types.NodeID{1},
postProvider,
poetDb,
[]string{},
[]string{poetProver.RestURL().String()},
t.TempDir(),
logtest.New(t),
sig,
PoetConfig{},
mclock,
withPoetClients([]PoetProvingServiceClient{poetProver}),
)
r.NoError(err)

Expand Down
56 changes: 50 additions & 6 deletions activation/poet.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
"github.com/hashicorp/go-retryablehttp"
rpcapi "github.com/spacemeshos/poet/release/proto/go/rpc/api/v1"
"github.com/spacemeshos/poet/shared"
"go.uber.org/zap"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"

"github.com/spacemeshos/go-spacemesh/common/types"
"github.com/spacemeshos/go-spacemesh/log"
)

var (
Expand All @@ -40,6 +40,7 @@
baseURL *url.URL
poetServiceID types.PoetServiceID
client *retryablehttp.Client
logger *zap.Logger
}

func defaultPoetClientFunc(address string, cfg PoetConfig) (PoetProvingServiceClient, error) {
Expand All @@ -53,6 +54,28 @@
return retryablehttp.DefaultRetryPolicy(ctx, resp, err)
}

// A wrapper around zap.Logger to make it compatible with
// retryablehttp.LeveledLogger interface.
type retryableHttpLogger struct {
inner *zap.Logger
}

func (r retryableHttpLogger) Error(format string, args ...any) {
r.inner.Sugar().Errorw(format, args...)
}

func (r retryableHttpLogger) Info(format string, args ...any) {
r.inner.Sugar().Infow(format, args...)

Check warning on line 68 in activation/poet.go

View check run for this annotation

Codecov / codecov/patch

activation/poet.go#L67-L68

Added lines #L67 - L68 were not covered by tests
}

func (r retryableHttpLogger) Warn(format string, args ...any) {
r.inner.Sugar().Warnw(format, args...)

Check warning on line 72 in activation/poet.go

View check run for this annotation

Codecov / codecov/patch

activation/poet.go#L71-L72

Added lines #L71 - L72 were not covered by tests
}

func (r retryableHttpLogger) Debug(format string, args ...any) {
r.inner.Sugar().Debugw(format, args...)
}

type PoetClientOpts func(*HTTPPoetClient)

func withCustomHttpClient(client *http.Client) PoetClientOpts {
Expand All @@ -61,11 +84,22 @@
}
}

func WithLogger(logger *zap.Logger) PoetClientOpts {
return func(c *HTTPPoetClient) {
c.logger = logger
c.client.Logger = &retryableHttpLogger{inner: logger}
fasmat marked this conversation as resolved.
Show resolved Hide resolved
c.client.ResponseLogHook = func(logger retryablehttp.Logger, resp *http.Response) {
c.logger.Info(
"response received",
zap.Stringer("url", resp.Request.URL),
zap.Int("status", resp.StatusCode),
)
}
}
}

// NewHTTPPoetClient returns new instance of HTTPPoetClient connecting to the specified url.
func NewHTTPPoetClient(baseUrl string, cfg PoetConfig, opts ...PoetClientOpts) (*HTTPPoetClient, error) {
// TODO(brozansk): Take a logger and use it instead of global logger
log.With().Info("creating poet client", log.String("url", baseUrl), log.Int("max_retries", cfg.MaxRequestRetries), log.Stringer("retry_delay", cfg.RequestRetryDelay))

client := &retryablehttp.Client{
RetryMax: cfg.MaxRequestRetries,
RetryWaitMin: cfg.RequestRetryDelay,
Expand All @@ -85,11 +119,20 @@
poetClient := &HTTPPoetClient{
baseURL: baseURL,
client: client,
logger: zap.NewNop(),
}
for _, opt := range opts {
opt(poetClient)
}

poetClient.logger.Info(
"created poet client",
zap.Stringer("url", baseURL),
zap.Int("max retries", client.RetryMax),
zap.Duration("min retry wait", client.RetryWaitMin),
zap.Duration("max retry wait", client.RetryWaitMax),
)

return poetClient, nil
}

Expand Down Expand Up @@ -211,8 +254,9 @@
return fmt.Errorf("reading response body (%w)", err)
}

log.GetLogger().WithContext(ctx).With().Debug("response from poet", log.String("status", res.Status), log.String("body", string(data)))

if res.StatusCode != http.StatusOK {
c.logger.Info("got poet response != 200 OK", zap.String("status", res.Status), zap.String("body", string(data)))
}

Check warning on line 259 in activation/poet.go

View check run for this annotation

Codecov / codecov/patch

activation/poet.go#L258-L259

Added lines #L258 - L259 were not covered by tests
switch res.StatusCode {
case http.StatusOK:
case http.StatusNotFound:
Expand Down
8 changes: 6 additions & 2 deletions activation/poet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"

"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
"golang.org/x/sync/errgroup"

"github.com/spacemeshos/go-spacemesh/common/types"
Expand All @@ -29,22 +30,25 @@ func TestHTTPPoet(t *testing.T) {

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c, err := NewHTTPPoetTestHarness(ctx, poetDir, DefaultPoetConfig())
c, err := NewHTTPPoetTestHarness(ctx, poetDir)
r.NoError(err)
r.NotNil(c)

eg.Go(func() error {
return c.Service.Start(ctx)
})

client, err := NewHTTPPoetClient(c.RestURL().String(), DefaultPoetConfig(), WithLogger(zaptest.NewLogger(t)))
require.NoError(t, err)

signer, err := signing.NewEdSigner(signing.WithPrefix([]byte("prefix")))
require.NoError(t, err)
ch := types.RandomHash()

signature := signer.Sign(signing.POET, ch.Bytes())
prefix := bytes.Join([][]byte{signer.Prefix(), {byte(signing.POET)}}, nil)

poetRound, err := c.Submit(context.Background(), prefix, ch.Bytes(), signature, signer.NodeID(), PoetPoW{})
poetRound, err := client.Submit(context.Background(), prefix, ch.Bytes(), signature, signer.NodeID(), PoetPoW{})
r.NoError(err)
r.NotNil(poetRound)
}
Expand Down
26 changes: 9 additions & 17 deletions activation/poet_test_harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ import (
// HTTPPoetTestHarness utilizes a local self-contained poet server instance
// targeted by an HTTP client. It is intended to be used in tests only.
type HTTPPoetTestHarness struct {
*HTTPPoetClient
Service *server.Server
}

func (h *HTTPPoetTestHarness) RestURL() *url.URL {
return &url.URL{
Scheme: "http",
Host: h.Service.GrpcRestProxyAddr().String(),
}
}

type HTTPPoetOpt func(*config.Config)

func WithGenesis(genesis time.Time) HTTPPoetOpt {
Expand Down Expand Up @@ -44,7 +50,7 @@ func WithCycleGap(gap time.Duration) HTTPPoetOpt {
}

// NewHTTPPoetTestHarness returns a new instance of HTTPPoetHarness.
func NewHTTPPoetTestHarness(ctx context.Context, poetdir string, clientCfg PoetConfig, opts ...HTTPPoetOpt) (*HTTPPoetTestHarness, error) {
func NewHTTPPoetTestHarness(ctx context.Context, poetdir string, opts ...HTTPPoetOpt) (*HTTPPoetTestHarness, error) {
cfg := config.DefaultConfig()
cfg.PoetDir = poetdir
cfg.RawRESTListener = "localhost:0"
Expand All @@ -64,21 +70,7 @@ func NewHTTPPoetTestHarness(ctx context.Context, poetdir string, clientCfg PoetC
return nil, err
}

// NewHTTPPoetClient takes an URL as connection string. Server speaks HTTP.
url := &url.URL{
Scheme: "http",
Host: poet.GrpcRestProxyAddr().String(),
}

client, err := NewHTTPPoetClient(url.String(), clientCfg)
if err != nil {
return nil, err
}

// TODO: query for the REST address to allow dynamic port allocation.
// It needs changes in poet.
return &HTTPPoetTestHarness{
HTTPPoetClient: client,
Service: poet,
Service: poet,
}, nil
}