diff --git a/api/server.go b/api/server.go index 15bab7f9..db562308 100644 --- a/api/server.go +++ b/api/server.go @@ -841,6 +841,16 @@ type ApiServer struct { openAudioPool *OpenAudioPool } +// requestLogger returns app.logger annotated with the current request_id (set +// by the requestid middleware) when available, so handler logs can be +// correlated with access logs. +func (app *ApiServer) requestLogger(c *fiber.Ctx) *zap.Logger { + if requestId, ok := c.Locals("requestId").(string); ok && requestId != "" { + return app.logger.With(zap.String("request_id", requestId)) + } + return app.logger +} + func (app *ApiServer) home(c *fiber.Ctx) error { return c.JSON(fiber.Map{ "env": app.config.Env, diff --git a/api/v1_claim_rewards.go b/api/v1_claim_rewards.go index abc6b83b..8a518c6e 100644 --- a/api/v1_claim_rewards.go +++ b/api/v1_claim_rewards.go @@ -212,6 +212,7 @@ func getValidatorAttestation(args GetValidatorAttestationParams) (*SenderAttesta // handling retries and reselection func fetchAttestations( ctx context.Context, + logger *zap.Logger, rewardClaim RewardClaim, allValidators []config.Node, excludedOperators []string, @@ -321,6 +322,14 @@ func fetchAttestations( for _, result := range results { if result.err != nil { + logger.Warn("validator attestation failed", + zap.String("validator", result.node.Endpoint), + zap.String("validatorOwner", result.node.Owner), + zap.String("handle", rewardClaim.Handle), + zap.String("rewardId", rewardClaim.RewardID), + zap.String("specifier", rewardClaim.Specifier), + zap.Error(result.err), + ) badValidators[result.node.Endpoint] = true continue } @@ -597,6 +606,7 @@ type RelayTransactionResponse struct { // Claims an individual reward. func claimReward( ctx context.Context, + logger *zap.Logger, rewardClaim RewardClaim, rewardManagerClient *reward_manager.RewardManagerClient, rewardAttester *rewards.RewardAttester, @@ -639,6 +649,7 @@ func claimReward( // Fetch AAO and validator attestations attestations, err := fetchAttestations( ctx, + logger, rewardClaim, validators, existingValidatorOwners, @@ -740,6 +751,7 @@ type ClaimRewardsBody struct { // Claims all the filtered undisbursed rewards for a user. func (app *ApiServer) v1ClaimRewards(c *fiber.Ctx) error { + logger := app.requestLogger(c) body := ClaimRewardsBody{} err := c.BodyParser(&body) @@ -831,6 +843,7 @@ func (app *ApiServer) v1ClaimRewards(c *fiber.Ctx) error { validators := app.config.ArtistCoinRewardsStaticSenders sigs, err := claimReward( ctx, + logger, rewardClaim, app.rewardManagerClient, app.rewardAttester, @@ -842,7 +855,7 @@ func (app *ApiServer) v1ClaimRewards(c *fiber.Ctx) error { if err != nil { var instrErr *spl.InstructionError if errors.As(err, &instrErr) { - app.logger.Error("failed to claim challenge reward. transaction failed to send.", + logger.Error("failed to claim challenge reward. transaction failed to send.", zap.String("handle", row.Handle.String), zap.String("rewardId", row.ChallengeID), zap.String("specifier", row.Specifier), @@ -851,7 +864,7 @@ func (app *ApiServer) v1ClaimRewards(c *fiber.Ctx) error { zap.Error(err), ) } else { - app.logger.Error("failed to claim challenge reward.", + logger.Error("failed to claim challenge reward.", zap.String("handle", row.Handle.String), zap.String("rewardId", row.ChallengeID), zap.String("specifier", row.Specifier), diff --git a/api/v1_claim_rewards_test.go b/api/v1_claim_rewards_test.go index 9cfb32ee..4384c129 100644 --- a/api/v1_claim_rewards_test.go +++ b/api/v1_claim_rewards_test.go @@ -11,6 +11,7 @@ import ( "github.com/OpenAudio/go-openaudio/pkg/rewards" "github.com/gagliardetto/solana-go" "github.com/stretchr/testify/assert" + "go.uber.org/zap" ) func TestFetchAttestations(t *testing.T) { @@ -106,6 +107,7 @@ func TestFetchAttestations(t *testing.T) { // Call fetchAttestations attestations, err := fetchAttestations( context.Background(), + zap.NewNop(), rewardClaim, allValidators, []string{}, // no excluded operators diff --git a/api/v1_coins_post_redeem.go b/api/v1_coins_post_redeem.go index f69f0298..7553b6bd 100644 --- a/api/v1_coins_post_redeem.go +++ b/api/v1_coins_post_redeem.go @@ -29,6 +29,7 @@ type CoinRewardParams struct { } func (app *ApiServer) v1CoinsPostRedeem(c *fiber.Ctx) error { + logger := app.requestLogger(c) // #region Validate Params if app.config.LaunchpadDeterministicSecret == "" { return fiber.NewError(fiber.StatusInternalServerError, "Claim authority base is not configured") @@ -332,6 +333,14 @@ func (app *ApiServer) v1CoinsPostRedeem(c *fiber.Ctx) error { }) if err != nil { + logger.Warn("validator attestation failed", + zap.String("validator", validator.Endpoint), + zap.String("validatorOwner", validator.Owner), + zap.String("handle", userHandle), + zap.String("rewardId", redeemCode), + zap.String("specifier", specifier), + zap.Error(err), + ) continue } @@ -342,6 +351,15 @@ func (app *ApiServer) v1CoinsPostRedeem(c *fiber.Ctx) error { } signatureBytes, err := hex.DecodeString(strings.TrimPrefix(signature, "0x")) if err != nil { + logger.Warn("validator attestation signature decode failed", + zap.String("validator", validator.Endpoint), + zap.String("validatorOwner", validator.Owner), + zap.String("handle", userHandle), + zap.String("rewardId", redeemCode), + zap.String("specifier", specifier), + zap.String("attestation", response.Attestation), + zap.Error(err), + ) continue } @@ -375,7 +393,7 @@ func (app *ApiServer) v1CoinsPostRedeem(c *fiber.Ctx) error { if err != nil { var instrErr *spl.InstructionError if errors.As(err, &instrErr) { - app.logger.Error("failed to claim challenge reward. transaction failed to send.", + logger.Error("failed to claim challenge reward. transaction failed to send.", zap.String("handle", userHandle), zap.String("rewardId", "code"), zap.String("specifier", specifier), @@ -384,7 +402,7 @@ func (app *ApiServer) v1CoinsPostRedeem(c *fiber.Ctx) error { zap.Error(err), ) } else { - app.logger.Error("failed to claim challenge reward.", + logger.Error("failed to claim challenge reward.", zap.String("handle", userHandle), zap.String("rewardId", "code"), zap.String("specifier", specifier),