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

feat: enhancement and add metric #5

Merged
merged 3 commits into from
Apr 25, 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
2 changes: 1 addition & 1 deletion .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
password: ${{ secrets.GH_TOKEN }}

- name: Push image
run: |
Expand Down
35 changes: 24 additions & 11 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ import (
)

type SyncerConfig struct {
BucketName string `json:"bucket_name"` // BucketName is the identifier of bucket on Greenfield that store blob
StartSlot uint64 `json:"start_slot"` // StartSlot is used to init the syncer which slot of beacon chain to synced from, only need to provide once.
CreateBundleSlotInterval uint64 `json:"create_bundle_slot_interval"` // CreateBundleSlotInterval defines the number of slot that syncer would assemble blobs and upload to bundle service
BundleServiceEndpoints []string `json:"bundle_service_endpoints"` // BundleServiceEndpoints is a list of bundle service address
BeaconRPCAddrs []string `json:"beacon_rpc_addrs"` // BeaconRPCAddrs is a list of beacon chain RPC address
ETHRPCAddrs []string `json:"eth_rpc_addrs"`
TempDir string `json:"temp_dir"` // TempDir is used to store blobs and created bundle
PrivateKey string `json:"private_key"` // PrivateKey is the key of bucket owner, request to bundle service will be signed by it as well.
DBConfig DBConfig `json:"db_config"`
MetricsConfig MetricsConfig `json:"metrics_config"`
LogConfig LogConfig `json:"log_config"`
BucketName string `json:"bucket_name"` // BucketName is the identifier of bucket on Greenfield that store blob
StartSlot uint64 `json:"start_slot"` // StartSlot is used to init the syncer which slot of beacon chain to synced from, only need to provide once.
CreateBundleSlotInterval uint64 `json:"create_bundle_slot_interval"` // CreateBundleSlotInterval defines the number of slot that syncer would assemble blobs and upload to bundle service
BundleServiceEndpoints []string `json:"bundle_service_endpoints"` // BundleServiceEndpoints is a list of bundle service address
BeaconRPCAddrs []string `json:"beacon_rpc_addrs"` // BeaconRPCAddrs is a list of beacon chain RPC address
ETHRPCAddrs []string `json:"eth_rpc_addrs"`
TempDir string `json:"temp_dir"` // TempDir is used to store blobs and created bundle
PrivateKey string `json:"private_key"` // PrivateKey is the key of bucket owner, request to bundle service will be signed by it as well.
BundleNotSealedReuploadThreshold int64 `json:"bundle_not_sealed_reupload_threshold"` // BundleNotSealedReuploadThreshold for re-uploading a bundle if it cant be sealed within the time threshold.
DBConfig DBConfig `json:"db_config"`
MetricsConfig MetricsConfig `json:"metrics_config"`
LogConfig LogConfig `json:"log_config"`
}

func (s *SyncerConfig) Validate() {
Expand Down Expand Up @@ -54,6 +55,10 @@ func (s *SyncerConfig) Validate() {
if s.CreateBundleSlotInterval > 30 {
panic("create_bundle_slot_interval is supposed less than 20")
}
if s.BundleNotSealedReuploadThreshold <= 60 {
panic("Bundle_not_sealed_reupload_threshold is supposed larger than 60")
}

s.DBConfig.Validate()
}

Expand All @@ -64,6 +69,13 @@ func (s *SyncerConfig) GetCreateBundleSlotInterval() uint64 {
return s.CreateBundleSlotInterval
}

func (s *SyncerConfig) GetReUploadBundleThresh() int64 {
if s.BundleNotSealedReuploadThreshold == 0 {
return DefaultReUploadBundleThreshold
}
return s.BundleNotSealedReuploadThreshold
}

type ServerConfig struct {
BucketName string `json:"bucket_name"`
BundleServiceEndpoints []string `json:"bundle_service_endpoints"` // BundleServiceEndpoints is a list of bundle service address
Expand Down Expand Up @@ -118,6 +130,7 @@ func (cfg *DBConfig) Validate() {
type MetricsConfig struct {
Enable bool `json:"enable"`
HttpAddress string `json:"http_address"`
SPEndpoint string `json:"sp_endpoint"`
}

type LogConfig struct {
Expand Down
3 changes: 3 additions & 0 deletions config/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ const (
EnvVarPrivateKey = "PRIVATE_KEY"

DefaultCreateBundleSlotInterval = 20

DefaultReUploadBundleThreshold = 3600 // in second

)
2 changes: 1 addition & 1 deletion db/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Block struct {
BlobCount int

BundleName string `gorm:"NOT NULL"`
Status Status
Status Status `gorm:"index:idx_block_status"`
}

func (*Block) TableName() string {
Expand Down
11 changes: 6 additions & 5 deletions db/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ type InnerBundleStatus int
const (
Finalizing InnerBundleStatus = 0
Finalized InnerBundleStatus = 1 // when a bundle is uploaded to bundle service, its status will be Finalized
Sealed InnerBundleStatus = 2 // todo The post verification process should check if a bundle is indeed sealed onchain
Sealed InnerBundleStatus = 2 //
Deprecated InnerBundleStatus = 3
)

type Bundle struct {
Id int64
Name string `gorm:"NOT NULL;uniqueIndex:idx_bundle_name;size:64"`
Status InnerBundleStatus `gorm:"NOT NULL"`
Calibrated bool
Id int64
Name string `gorm:"NOT NULL;uniqueIndex:idx_bundle_name;size:64"`
Status InnerBundleStatus `gorm:"NOT NULL"`
Calibrated bool
CreatedTime int64 `gorm:"NOT NULL;comment:created_time"`
}

func (*Bundle) TableName() string {
Expand Down
10 changes: 4 additions & 6 deletions external/beacon_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ const (
)

type BeaconClient struct {
hc *http.Client
timeout time.Duration
host string
hc *http.Client
host string
}

// NewBeaconClient returns a new beacon client.
func NewBeaconClient(host string, timeout time.Duration) (*BeaconClient, error) {
func NewBeaconClient(host string) (*BeaconClient, error) {
transport := &http.Transport{
DisableCompression: true,
MaxIdleConnsPerHost: 1000,
Expand All @@ -41,8 +40,7 @@ func NewBeaconClient(host string, timeout time.Duration) (*BeaconClient, error)
Timeout: 10 * time.Minute,
Transport: transport,
}
return &BeaconClient{hc: client,
timeout: timeout, host: host}, nil
return &BeaconClient{hc: client, host: host}, nil
}

func (c *BeaconClient) GetBlob(ctx context.Context, slotNumber uint64) ([]*structs.Sidecar, error) {
Expand Down
2 changes: 1 addition & 1 deletion external/eth_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func NewETHClient(rpcAddrs, beaconRPCAddrs string) *ETHClient {
if err != nil {
panic("new eth client error")
}
beaconClient, err := NewBeaconClient(beaconRPCAddrs, time.Second*3)
beaconClient, err := NewBeaconClient(beaconRPCAddrs)
if err != nil {
panic("new eth client error")
}
Expand Down
63 changes: 63 additions & 0 deletions external/sp_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package external

import (
"context"
"encoding/xml"
"net/http"
"strconv"
"strings"
"time"
)

type SPClient struct {
hc *http.Client
host string
}

func NewSPClient(host string) (*SPClient, error) {
transport := &http.Transport{
DisableCompression: true,
MaxIdleConnsPerHost: 1000,
MaxConnsPerHost: 1000,
IdleConnTimeout: 90 * time.Second,
}
client := &http.Client{
Timeout: 10 * time.Minute,
Transport: transport,
}
return &SPClient{hc: client, host: host}, nil
}

func (c *SPClient) GetBucketReadQuota(ctx context.Context, bucketName string) (QuotaInfo, error) {
year, month, _ := time.Now().Date()
var date string
if int(month) < 10 {
date = strconv.Itoa(year) + "-" + "0" + strconv.Itoa(int(month))
} else {
date = strconv.Itoa(year) + "-" + strconv.Itoa(int(month))
}
var urlStr string
parts := strings.Split(c.host, "//")
urlStr = parts[0] + "//" + bucketName + "." + parts[1] + "/"

req, err := http.NewRequestWithContext(ctx, http.MethodGet, urlStr, nil)
if err != nil {
return QuotaInfo{}, err
}
// set query parameters
q := req.URL.Query()
q.Add("read-quota", "")
q.Add("year-month", date)
req.URL.RawQuery = q.Encode()
resp, err := c.hc.Do(req)
if err != nil {
return QuotaInfo{}, err
}
defer resp.Body.Close()
QuotaResult := QuotaInfo{}
err = xml.NewDecoder(resp.Body).Decode(&QuotaResult)
if err != nil {
return QuotaInfo{}, err
}
return QuotaResult, nil
}
19 changes: 19 additions & 0 deletions external/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package external

import (
"encoding/xml"
)

// QuotaInfo indicates the quota info of bucket
type QuotaInfo struct {
XMLName xml.Name `xml:"GetReadQuotaResult"`
Version string `xml:"version,attr"`
BucketName string `xml:"BucketName"`
BucketID string `xml:"BucketID"` // BucketID defines the bucket read quota value on chain
ReadQuotaSize uint64 `xml:"ReadQuotaSize"` // ReadQuotaSize defines the bucket read quota value on chain
SPFreeReadQuotaSize uint64 `xml:"SPFreeReadQuotaSize"` // SPFreeReadQuotaSize defines the free quota of this month
ReadConsumedSize uint64 `xml:"ReadConsumedSize"` // ReadConsumedSize defines the consumed total read quota of this month
FreeConsumedSize uint64 `xml:"FreeConsumedSize"` // FreeConsumedSize defines the consumed free quota
MonthlyFreeQuota uint64 `xml:"MonthlyFreeQuota"` // MonthlyFreeQuota defines the consumed monthly free quota
MonthlyFreeConsumedSize uint64 `xml:"MonthlyQuotaConsumedSize"` // MonthlyFreeConsumedSize defines the consumed monthly free quota
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/prysmaticlabs/prysm/v5 v5.0.2
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.4
golang.org/x/net v0.21.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/driver/mysql v1.5.1
Expand All @@ -40,6 +41,7 @@ require (
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.5.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
Expand Down Expand Up @@ -72,6 +74,7 @@ require (
github.com/oklog/ulid v1.3.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
Expand Down
3 changes: 1 addition & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bits-and-blooms/bitset v1.11.0 h1:RMyy2mBBShArUAhfVRZJ2xyBO58KCBCtZFShw3umo6k=
github.com/bits-and-blooms/bitset v1.11.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bnb-chain/blob-syncer v0.0.1 h1:GImArcAzx23ntV2l8dOrPJX11YiAoMWXsRh3JLfHQKc=
github.com/bnb-chain/blob-syncer v0.0.1/go.mod h1:7JAEkO3ID/Kj56eyRV4SpiIf2vi1/czOYrlv3Z7XMBQ=
github.com/bnb-chain/greenfield-bundle-sdk v1.1.0 h1:0BWQsV+c32wHxEEpJY9igBSBg5N1Fm3KoSLC+Yef2n0=
github.com/bnb-chain/greenfield-bundle-sdk v1.1.0/go.mod h1:NCjQp0sniAbBR5yR5pYiXpYwYd1okSIBLj+31sTpmXA=
github.com/btcsuite/btcd v0.23.3 h1:4KH/JKy9WiCd+iUS9Mu0Zp7Dnj17TGdKrg9xc/FGj24=
Expand Down Expand Up @@ -415,6 +413,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
Expand Down
3 changes: 1 addition & 2 deletions logging/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ package logging
import (
"os"

"gopkg.in/natefinch/lumberjack.v2"

"github.com/op/go-logging"
"gopkg.in/natefinch/lumberjack.v2"

"github.com/bnb-chain/blob-hub/config"
)
Expand Down
6 changes: 6 additions & 0 deletions metrics/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ var (
Help: "Verified slot number, all blobs have been verified against the bundle service.",
})

BucketRemainingQuotaGauge = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "bucket_remaining_quota",
Help: "Remaining read quota of bucket in bytes",
})

MetricsItems = []prometheus.Collector{
SyncedSlotGauge,
VerifiedSlotGauge,
BucketRemainingQuotaGauge,
}
)

Expand Down
10 changes: 5 additions & 5 deletions restapi/configure_blob_hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import (
"net/http"
"os"

"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/swag"

"github.com/bnb-chain/blob-hub/cache"
"github.com/bnb-chain/blob-hub/config"
syncerdb "github.com/bnb-chain/blob-hub/db"
"github.com/bnb-chain/blob-hub/external"
"github.com/bnb-chain/blob-hub/restapi/handlers"
"github.com/bnb-chain/blob-hub/service"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/swag"

"github.com/bnb-chain/blob-hub/restapi/operations"
"github.com/bnb-chain/blob-hub/restapi/operations/blob"
"github.com/bnb-chain/blob-hub/service"
)

//go:generate swagger generate server --target ../../blob-syncer --name BlobHub --spec ../swagger.yaml --principal interface{}
Expand Down
26 changes: 26 additions & 0 deletions syncer/monitor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package syncer

import (
"context"
"time"

"github.com/bnb-chain/blob-hub/logging"
"github.com/bnb-chain/blob-hub/metrics"
)

func (s *BlobSyncer) monitorQuota() {
if s.spClient == nil {
return
}
monitorTicket := time.NewTicker(MonitorQuotaInterval)
for range monitorTicket.C {
quota, err := s.spClient.GetBucketReadQuota(context.Background(), s.getBucketName())
if err != nil {
logging.Logger.Errorf("failed to get bucket info from SP, err=%s", err.Error())
continue
}
remaining := quota.ReadQuotaSize + quota.MonthlyFreeQuota + quota.SPFreeReadQuotaSize - quota.ReadConsumedSize - quota.MonthlyFreeConsumedSize - quota.FreeConsumedSize
metrics.BucketRemainingQuotaGauge.Set(float64(remaining))
logging.Logger.Infof("remaining quota in bytes is %d", remaining)
}
}
Loading
Loading