From 414a7cfd8fe00db166a88ec86a31fc86e7296b0e Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 28 Jun 2023 10:32:30 -0700 Subject: [PATCH 01/63] add tps --- cmd/simulator/txs/agent.go | 96 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 cmd/simulator/txs/agent.go diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go new file mode 100644 index 0000000000..006e77106c --- /dev/null +++ b/cmd/simulator/txs/agent.go @@ -0,0 +1,96 @@ +// (c) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package txs + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/ethereum/go-ethereum/log" +) + +// TxSequence provides an interface to return a channel of transactions. +// The sequence is responsible for closing the channel when there are no further +// transactions. +type TxSequence[T any] interface { + Chan() <-chan T +} + +// Worker defines the interface for issuance and confirmation of transactions. +// The caller is responsible for calling Close to cleanup resources used by the +// worker at the end of the simulation. +type Worker[T any] interface { + IssueTx(ctx context.Context, tx T) error + ConfirmTx(ctx context.Context, tx T) error + Close(ctx context.Context) error +} + +// Execute the work of the given agent. +type Agent[T any] interface { + Execute(ctx context.Context) error +} + +// issueNAgent issues and confirms a batch of N transactions at a time. +type issueNAgent[T any] struct { + sequence TxSequence[T] + worker Worker[T] + n uint64 +} + +// NewIssueNAgent creates a new issueNAgent +func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64) Agent[T] { + return &issueNAgent[T]{ + sequence: sequence, + worker: worker, + n: n, + } +} + +// Execute issues txs in batches of N and waits for them to confirm +func (a issueNAgent[T]) Execute(ctx context.Context) error { + if a.n == 0 { + return errors.New("batch size n cannot be equal to 0") + } + + txChan := a.sequence.Chan() + totalTxs := len(txChan) + confirmedCount := 0 + start := time.Now() + + for { + var ( + txs = make([]T, 0, a.n) + tx T + done bool + ) + for i := uint64(0); i < a.n; i++ { + select { + case tx, done = <-txChan: + if !done { + return a.worker.Close(ctx) + } + case <-ctx.Done(): + return ctx.Err() + } + + if err := a.worker.IssueTx(ctx, tx); err != nil { + return fmt.Errorf("failed to issue transaction %d: %w", len(txs), err) + } + txs = append(txs, tx) + } + + for i, tx := range txs { + if err := a.worker.ConfirmTx(ctx, tx); err != nil { + return fmt.Errorf("failed to await transaction %d: %w", i, err) + } + confirmedCount++ + if confirmedCount == totalTxs { + totalTime := time.Since(start).Seconds() + log.Info("Execution complete", "totalTxs", totalTxs, "totalTime", totalTime, "TPS", float64(totalTxs)/totalTime) + } + } + } +} From bf74d46899638571a3f42a3353792e462d5c0b2e Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 28 Jun 2023 14:55:40 -0700 Subject: [PATCH 02/63] get block build metrics --- cmd/simulator/txs/agent.go | 23 +++++++++++++++++++++++ ethclient/ethclient.go | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 3a85f0d713..1227782b4d 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -7,6 +7,9 @@ import ( "context" "errors" "fmt" + "io/ioutil" + "net/http" + "regexp" "time" "github.com/ethereum/go-ethereum/log" @@ -90,7 +93,27 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { if confirmedCount == totalTxs { totalTime := time.Since(start).Seconds() log.Info("Execution complete", "totalTxs", totalTxs, "totalTime", totalTime, "TPS", float64(totalTxs)/totalTime) + logOtherMetrics() } } } } + +func logOtherMetrics() error { + resp, err := http.Get("http://127.0.0.1:9650/ext/metrics") + if err != nil { + return fmt.Errorf("failed getting metrics: %w", err) + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("failed reading response body of metrics: %w", err) + } + + bodyString := string(body) + re := regexp.MustCompile(".*avalanche_C_vm_metervm_build_block_sum.*") + matches := re.FindAllStringSubmatch(bodyString, -1) + + log.Info("Metrics", "results", matches[len(matches)-1]) + return nil +} diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index b46118eb0c..4530e9e645 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -384,7 +384,7 @@ func (ec *client) SubscribeNewAcceptedTransactions(ctx context.Context, ch chan< return ec.c.EthSubscribe(ctx, ch, "newAcceptedTransactions") } -// SubscribeNewAcceptedTransactions subscribes to notifications about the accepted transaction hashes on the given channel. +// SubscribeNewPendingTransactions subscribes to notifications about the pending transaction hashes on the given channel. func (ec *client) SubscribeNewPendingTransactions(ctx context.Context, ch chan<- *common.Hash) (interfaces.Subscription, error) { return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions") } From 0ed532e99464b73655f748403e3921574305a5d4 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 09:12:13 -0700 Subject: [PATCH 03/63] Add issuance time, confirmed time, issued-> acceptance time, verify time --- cmd/simulator/txs/agent.go | 41 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 1227782b4d..d7805ac499 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -61,6 +61,11 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { txChan := a.sequence.Chan() totalTxs := len(txChan) confirmedCount := 0 + + // Start the issuedTime and cofirmedTime at the zero time + issuedTime := time.Time{} + confirmedTime := time.Time{} + start := time.Now() for { @@ -69,6 +74,8 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { tx T ok bool ) + // Start issuance batch + issuedStart := time.Now() for i := uint64(0); i < a.n; i++ { select { case tx, ok = <-txChan: @@ -84,18 +91,40 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { } txs = append(txs, tx) } + issuedEnd := time.Now() + // Add the issuance batch time to the total issuedTime + issuedDuration := issuedEnd.Sub(issuedStart) + issuedTime = issuedTime.Add(issuedDuration) + // Start confirmation batch + confirmedStart := time.Now() for i, tx := range txs { if err := a.worker.ConfirmTx(ctx, tx); err != nil { return fmt.Errorf("failed to await transaction %d: %w", i, err) } confirmedCount++ if confirmedCount == totalTxs { + // Mark the final ending time + confirmedEnd := time.Now() totalTime := time.Since(start).Seconds() - log.Info("Execution complete", "totalTxs", totalTxs, "totalTime", totalTime, "TPS", float64(totalTxs)/totalTime) + // Get the last confirmed batch time and add it to the total confirmedTime + confirmedDuration := confirmedEnd.Sub(confirmedStart) + confirmedTime = confirmedTime.Add(confirmedDuration) + // Get the final duration by comparing it to the zero time + issuedFinalDuration := issuedTime.Sub(time.Time{}) + confirmedFinalDuration := confirmedTime.Sub(time.Time{}) + + log.Info("Execution complete", "totalTxs", totalTxs, "totalTime", totalTime, "TPS", float64(totalTxs)/totalTime, + "issuanceTime", issuedFinalDuration.Seconds(), "confirmedTime", confirmedFinalDuration.Seconds()) logOtherMetrics() } } + + confirmedEnd := time.Now() + // Add the confirmed batch time to the total confirmedTime + confirmedDuration := confirmedEnd.Sub(confirmedStart) + confirmedTime = confirmedTime.Add(confirmedDuration) + } } @@ -113,7 +142,15 @@ func logOtherMetrics() error { bodyString := string(body) re := regexp.MustCompile(".*avalanche_C_vm_metervm_build_block_sum.*") matches := re.FindAllStringSubmatch(bodyString, -1) + log.Info("Sum of time (in ns) of a build_block", "time", matches[len(matches)-1]) + + re = regexp.MustCompile(".*avalanche_C_blks_accepted_sum.*") + matches = re.FindAllStringSubmatch(bodyString, -1) + log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", matches[len(matches)-1]) + + re = regexp.MustCompile(".*avalanche_C_vm_metervm_verify_sum.*") + matches = re.FindAllStringSubmatch(bodyString, -1) + log.Info("Sum of time (in ns) of a verify", "time", matches[len(matches)-1]) - log.Info("Metrics", "results", matches[len(matches)-1]) return nil } From cedb3b05f6acdde1dab16d703a722ca860d3c4c7 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 09:23:39 -0700 Subject: [PATCH 04/63] Log times at end of batch --- cmd/simulator/txs/agent.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index d7805ac499..a876b48cee 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -61,6 +61,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { txChan := a.sequence.Chan() totalTxs := len(txChan) confirmedCount := 0 + batchI := 1 // Start the issuedTime and cofirmedTime at the zero time issuedTime := time.Time{} @@ -92,8 +93,9 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { txs = append(txs, tx) } issuedEnd := time.Now() - // Add the issuance batch time to the total issuedTime issuedDuration := issuedEnd.Sub(issuedStart) + log.Info("Issuance Batch Done", "batch", batchI, "time", issuedDuration.Seconds()) + // Add the issuance batch time to the total issuedTime issuedTime = issuedTime.Add(issuedDuration) // Start confirmation batch @@ -121,10 +123,11 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { } confirmedEnd := time.Now() - // Add the confirmed batch time to the total confirmedTime confirmedDuration := confirmedEnd.Sub(confirmedStart) + // Add the confirmed batch time to the total confirmedTime confirmedTime = confirmedTime.Add(confirmedDuration) - + log.Info("Confirmed Batch Done", "batch", batchI, "time", confirmedDuration.Seconds()) + batchI++ } } From 461c2c667850ee96b920271594b3a7683efede1f Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 09:26:59 -0700 Subject: [PATCH 05/63] cleaner --- cmd/simulator/txs/agent.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index a876b48cee..be8d7fb956 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -111,7 +111,9 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { totalTime := time.Since(start).Seconds() // Get the last confirmed batch time and add it to the total confirmedTime confirmedDuration := confirmedEnd.Sub(confirmedStart) + log.Info("Confirmed Batch Done", "batch", batchI, "time", confirmedDuration.Seconds()) confirmedTime = confirmedTime.Add(confirmedDuration) + // Get the final duration by comparing it to the zero time issuedFinalDuration := issuedTime.Sub(time.Time{}) confirmedFinalDuration := confirmedTime.Sub(time.Time{}) @@ -119,14 +121,15 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { log.Info("Execution complete", "totalTxs", totalTxs, "totalTime", totalTime, "TPS", float64(totalTxs)/totalTime, "issuanceTime", issuedFinalDuration.Seconds(), "confirmedTime", confirmedFinalDuration.Seconds()) logOtherMetrics() + return nil } } confirmedEnd := time.Now() confirmedDuration := confirmedEnd.Sub(confirmedStart) + log.Info("Confirmed Batch Done", "batch", batchI, "time", confirmedDuration.Seconds()) // Add the confirmed batch time to the total confirmedTime confirmedTime = confirmedTime.Add(confirmedDuration) - log.Info("Confirmed Batch Done", "batch", batchI, "time", confirmedDuration.Seconds()) batchI++ } } From 750ed9f38074d7ef54a8af64b782601797874414 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 10:35:42 -0700 Subject: [PATCH 06/63] address comments --- cmd/simulator/txs/agent.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index be8d7fb956..f7de887f91 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -135,7 +135,12 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { } func logOtherMetrics() error { + getCallStart := time.Now() resp, err := http.Get("http://127.0.0.1:9650/ext/metrics") + getCallEnd := time.Now() + getCallDuration := getCallEnd.Sub(getCallStart) + + log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) if err != nil { return fmt.Errorf("failed getting metrics: %w", err) } From 5c521d7974c34995a029e1d32f0ece28800b9b01 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 12:07:33 -0700 Subject: [PATCH 07/63] remove unused code block --- cmd/simulator/txs/agent.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index f7de887f91..7491567a22 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -63,34 +63,33 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { confirmedCount := 0 batchI := 1 - // Start the issuedTime and cofirmedTime at the zero time + // Start the issuedTime and confirmedTime at the zero time issuedTime := time.Time{} confirmedTime := time.Time{} - start := time.Now() + defer func() error { + return a.worker.Close(ctx) + }() + // Start time for execution + start := time.Now() for { var ( txs = make([]T, 0, a.n) tx T - ok bool ) // Start issuance batch issuedStart := time.Now() for i := uint64(0); i < a.n; i++ { select { - case tx, ok = <-txChan: - if !ok { - return a.worker.Close(ctx) - } case <-ctx.Done(): return ctx.Err() + case tx = <-txChan: + if err := a.worker.IssueTx(ctx, tx); err != nil { + return fmt.Errorf("failed to issue transaction %d: %w", len(txs), err) + } + txs = append(txs, tx) } - - if err := a.worker.IssueTx(ctx, tx); err != nil { - return fmt.Errorf("failed to issue transaction %d: %w", len(txs), err) - } - txs = append(txs, tx) } issuedEnd := time.Now() issuedDuration := issuedEnd.Sub(issuedStart) @@ -105,6 +104,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { return fmt.Errorf("failed to await transaction %d: %w", i, err) } confirmedCount++ + // We want the exact moment when all the txs have been confirmed if confirmedCount == totalTxs { // Mark the final ending time confirmedEnd := time.Now() From 3655c6656b71d2e5f163e02776710e7890dff33c Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Thu, 29 Jun 2023 12:34:11 -0700 Subject: [PATCH 08/63] avoids taking len of channel --- cmd/simulator/txs/agent.go | 57 ++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 7491567a22..4d9b4dc786 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -59,13 +59,14 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { } txChan := a.sequence.Chan() - totalTxs := len(txChan) confirmedCount := 0 batchI := 1 - // Start the issuedTime and confirmedTime at the zero time - issuedTime := time.Time{} - confirmedTime := time.Time{} + // Tracks the total amount of time waiting for issuing and confirming txs + var ( + totalIssuedTime time.Duration + totalConfirmedTime time.Duration + ) defer func() error { return a.worker.Close(ctx) @@ -75,16 +76,21 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { start := time.Now() for { var ( - txs = make([]T, 0, a.n) - tx T + txs = make([]T, 0, a.n) + tx T + moreTxs bool ) // Start issuance batch issuedStart := time.Now() + L: for i := uint64(0); i < a.n; i++ { select { case <-ctx.Done(): return ctx.Err() - case tx = <-txChan: + case tx, moreTxs = <-txChan: + if !moreTxs { + break L + } if err := a.worker.IssueTx(ctx, tx); err != nil { return fmt.Errorf("failed to issue transaction %d: %w", len(txs), err) } @@ -95,7 +101,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { issuedDuration := issuedEnd.Sub(issuedStart) log.Info("Issuance Batch Done", "batch", batchI, "time", issuedDuration.Seconds()) // Add the issuance batch time to the total issuedTime - issuedTime = issuedTime.Add(issuedDuration) + totalIssuedTime += issuedDuration // Start confirmation batch confirmedStart := time.Now() @@ -104,32 +110,23 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { return fmt.Errorf("failed to await transaction %d: %w", i, err) } confirmedCount++ - // We want the exact moment when all the txs have been confirmed - if confirmedCount == totalTxs { - // Mark the final ending time - confirmedEnd := time.Now() - totalTime := time.Since(start).Seconds() - // Get the last confirmed batch time and add it to the total confirmedTime - confirmedDuration := confirmedEnd.Sub(confirmedStart) - log.Info("Confirmed Batch Done", "batch", batchI, "time", confirmedDuration.Seconds()) - confirmedTime = confirmedTime.Add(confirmedDuration) - - // Get the final duration by comparing it to the zero time - issuedFinalDuration := issuedTime.Sub(time.Time{}) - confirmedFinalDuration := confirmedTime.Sub(time.Time{}) - - log.Info("Execution complete", "totalTxs", totalTxs, "totalTime", totalTime, "TPS", float64(totalTxs)/totalTime, - "issuanceTime", issuedFinalDuration.Seconds(), "confirmedTime", confirmedFinalDuration.Seconds()) - logOtherMetrics() - return nil - } } - + // Mark the final ending time confirmedEnd := time.Now() + // Get the last confirmed batch time and add it to the total confirmedTime confirmedDuration := confirmedEnd.Sub(confirmedStart) log.Info("Confirmed Batch Done", "batch", batchI, "time", confirmedDuration.Seconds()) - // Add the confirmed batch time to the total confirmedTime - confirmedTime = confirmedTime.Add(confirmedDuration) + totalConfirmedTime += confirmedDuration + + // Check if this is the last batch, if so write the final log and return + if !moreTxs { + totalTime := time.Since(start).Seconds() + log.Info("Execution complete", "totalTxs", confirmedCount, "totalTime", totalTime, "TPS", float64(confirmedCount)/totalTime, + "issuanceTime", totalIssuedTime.Seconds(), "confirmedTime", totalConfirmedTime.Seconds()) + logOtherMetrics() + return nil + } + batchI++ } } From 7b0f66331199908d6676c45712bcee0d0df634a9 Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Thu, 29 Jun 2023 12:37:16 -0700 Subject: [PATCH 09/63] nits --- cmd/simulator/txs/agent.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 4d9b4dc786..7edea81aed 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -97,13 +97,12 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { txs = append(txs, tx) } } - issuedEnd := time.Now() - issuedDuration := issuedEnd.Sub(issuedStart) + // Get the batch's issuance time and add it to totalIssuedTime + issuedDuration := time.Since(issuedStart) log.Info("Issuance Batch Done", "batch", batchI, "time", issuedDuration.Seconds()) - // Add the issuance batch time to the total issuedTime totalIssuedTime += issuedDuration - // Start confirmation batch + // Wait for txs in this batch to confirm confirmedStart := time.Now() for i, tx := range txs { if err := a.worker.ConfirmTx(ctx, tx); err != nil { @@ -111,10 +110,8 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { } confirmedCount++ } - // Mark the final ending time - confirmedEnd := time.Now() - // Get the last confirmed batch time and add it to the total confirmedTime - confirmedDuration := confirmedEnd.Sub(confirmedStart) + // Get the batch's confirmation time and add it to totalConfirmedTime + confirmedDuration := time.Since(confirmedStart) log.Info("Confirmed Batch Done", "batch", batchI, "time", confirmedDuration.Seconds()) totalConfirmedTime += confirmedDuration From be68d420d5a3213312b989c08706d030820d0172 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 14:01:06 -0700 Subject: [PATCH 10/63] pass in stringID --- cmd/simulator/load/funder.go | 5 +++-- cmd/simulator/load/loader.go | 13 +++++++++++-- cmd/simulator/txs/agent.go | 26 ++++++++++++++------------ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index 995cae9203..e3ec6af3bf 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -21,7 +21,7 @@ import ( // DistributeFunds ensures that each address in keys has at least [minFundsPerAddr] by sending funds // from the key with the highest starting balance. // This function returns a set of at least [numKeys] keys, each having a minimum balance [minFundsPerAddr]. -func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int) ([]*key.Key, error) { +func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int, blockchainID string) ([]*key.Key, error) { if len(keys) < numKeys { return nil, fmt.Errorf("insufficient number of keys %d < %d", len(keys), numKeys) } @@ -107,7 +107,8 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K return nil, fmt.Errorf("failed to generate fund distribution sequence from %s of length %d", maxFundsKey.Address, len(needFundsAddrs)) } worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) - txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs) + + txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs, blockchainID) if err := txFunderAgent.Execute(ctx); err != nil { return nil, err diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 779128e986..afbe733b82 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -8,6 +8,7 @@ import ( "crypto/ecdsa" "fmt" "math/big" + "regexp" "github.com/ava-labs/subnet-evm/cmd/simulator/config" "github.com/ava-labs/subnet-evm/cmd/simulator/key" @@ -31,6 +32,14 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // Construct the arguments for the load simulator clients := make([]ethclient.Client, 0, len(config.Endpoints)) + // Extract blockchainStrID from the clientURI + re := regexp.MustCompile(`bc\/(.*)\/ws`) + matches := re.FindStringSubmatch(config.Endpoints[0]) + if len(matches) < 1 { + return fmt.Errorf("failed to get blockchainStrID from the clientURI %s", config.Endpoints[0]) + } + // Get the last element in matches + blockchainIDStr := matches[len(matches)-1] for i := 0; i < config.Workers; i++ { clientURI := config.Endpoints[i%len(config.Endpoints)] client, err := ethclient.Dial(clientURI) @@ -63,7 +72,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { maxFeeCap := new(big.Int).Mul(big.NewInt(params.GWei), big.NewInt(config.MaxFeeCap)) minFundsPerAddr := new(big.Int).Mul(maxFeeCap, big.NewInt(int64(config.TxsPerWorker*params.TxGas))) log.Info("Distributing funds", "numTxsPerWorker", config.TxsPerWorker, "minFunds", minFundsPerAddr) - keys, err = DistributeFunds(ctx, clients[0], keys, config.Workers, minFundsPerAddr) + keys, err = DistributeFunds(ctx, clients[0], keys, config.Workers, minFundsPerAddr, blockchainIDStr) if err != nil { return err } @@ -112,7 +121,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { log.Info("Constructing tx agents...", "numAgents", config.Workers) agents := make([]txs.Agent[*types.Transaction], 0, config.Workers) for i := 0; i < config.Workers; i++ { - agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) + agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize, blockchainIDStr)) } log.Info("Starting tx agents...") diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 7edea81aed..a85cf48eb6 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -38,17 +38,19 @@ type Agent[T any] interface { // issueNAgent issues and confirms a batch of N transactions at a time. type issueNAgent[T any] struct { - sequence TxSequence[T] - worker Worker[T] - n uint64 + sequence TxSequence[T] + worker Worker[T] + n uint64 + blockchainIDStr string } // NewIssueNAgent creates a new issueNAgent -func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64) Agent[T] { +func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64, blockchainIDStr string) Agent[T] { return &issueNAgent[T]{ - sequence: sequence, - worker: worker, - n: n, + sequence: sequence, + worker: worker, + n: n, + blockchainIDStr: blockchainIDStr, } } @@ -120,7 +122,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { totalTime := time.Since(start).Seconds() log.Info("Execution complete", "totalTxs", confirmedCount, "totalTime", totalTime, "TPS", float64(confirmedCount)/totalTime, "issuanceTime", totalIssuedTime.Seconds(), "confirmedTime", totalConfirmedTime.Seconds()) - logOtherMetrics() + logOtherMetrics(a.blockchainIDStr) return nil } @@ -128,7 +130,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { } } -func logOtherMetrics() error { +func logOtherMetrics(blockchainIDStr string) error { getCallStart := time.Now() resp, err := http.Get("http://127.0.0.1:9650/ext/metrics") getCallEnd := time.Now() @@ -145,15 +147,15 @@ func logOtherMetrics() error { } bodyString := string(body) - re := regexp.MustCompile(".*avalanche_C_vm_metervm_build_block_sum.*") + re := regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) matches := re.FindAllStringSubmatch(bodyString, -1) log.Info("Sum of time (in ns) of a build_block", "time", matches[len(matches)-1]) - re = regexp.MustCompile(".*avalanche_C_blks_accepted_sum.*") + re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) matches = re.FindAllStringSubmatch(bodyString, -1) log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", matches[len(matches)-1]) - re = regexp.MustCompile(".*avalanche_C_vm_metervm_verify_sum.*") + re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) matches = re.FindAllStringSubmatch(bodyString, -1) log.Info("Sum of time (in ns) of a verify", "time", matches[len(matches)-1]) From 173f8475ca35f00b835f58a551324375c4b83858 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 15:47:21 -0700 Subject: [PATCH 11/63] move to loader --- cmd/simulator/load/funder.go | 2 +- cmd/simulator/load/loader.go | 39 ++++++++++++++++++++++++++++++- cmd/simulator/txs/agent.go | 45 ++++-------------------------------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index e3ec6af3bf..f360d5d259 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -108,7 +108,7 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K } worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) - txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs, blockchainID) + txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs) if err := txFunderAgent.Execute(ctx); err != nil { return nil, err diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index afbe733b82..813158f484 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -7,8 +7,11 @@ import ( "context" "crypto/ecdsa" "fmt" + "io/ioutil" "math/big" + "net/http" "regexp" + "time" "github.com/ava-labs/subnet-evm/cmd/simulator/config" "github.com/ava-labs/subnet-evm/cmd/simulator/key" @@ -121,7 +124,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { log.Info("Constructing tx agents...", "numAgents", config.Workers) agents := make([]txs.Agent[*types.Transaction], 0, config.Workers) for i := 0; i < config.Workers; i++ { - agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize, blockchainIDStr)) + agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) } log.Info("Starting tx agents...") @@ -138,5 +141,39 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { return err } log.Info("Tx agents completed successfully.") + + logOtherMetrics(blockchainIDStr) + return nil +} + +func logOtherMetrics(blockchainIDStr string) error { + getCallStart := time.Now() + resp, err := http.Get("http://127.0.0.1:9650/ext/metrics") + getCallEnd := time.Now() + getCallDuration := getCallEnd.Sub(getCallStart) + + log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) + if err != nil { + return fmt.Errorf("failed getting metrics: %w", err) + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("failed reading response body of metrics: %w", err) + } + + bodyString := string(body) + re := regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) + matches := re.FindAllStringSubmatch(bodyString, -1) + log.Info("Sum of time (in ns) of a build_block", "time", matches[len(matches)-1]) + + re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) + matches = re.FindAllStringSubmatch(bodyString, -1) + log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", matches[len(matches)-1]) + + re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) + matches = re.FindAllStringSubmatch(bodyString, -1) + log.Info("Sum of time (in ns) of a verify", "time", matches[len(matches)-1]) + return nil } diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index a85cf48eb6..beafce9929 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -7,9 +7,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" - "net/http" - "regexp" "time" "github.com/ethereum/go-ethereum/log" @@ -45,12 +42,11 @@ type issueNAgent[T any] struct { } // NewIssueNAgent creates a new issueNAgent -func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64, blockchainIDStr string) Agent[T] { +func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64) Agent[T] { return &issueNAgent[T]{ - sequence: sequence, - worker: worker, - n: n, - blockchainIDStr: blockchainIDStr, + sequence: sequence, + worker: worker, + n: n, } } @@ -122,42 +118,9 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { totalTime := time.Since(start).Seconds() log.Info("Execution complete", "totalTxs", confirmedCount, "totalTime", totalTime, "TPS", float64(confirmedCount)/totalTime, "issuanceTime", totalIssuedTime.Seconds(), "confirmedTime", totalConfirmedTime.Seconds()) - logOtherMetrics(a.blockchainIDStr) return nil } batchI++ } } - -func logOtherMetrics(blockchainIDStr string) error { - getCallStart := time.Now() - resp, err := http.Get("http://127.0.0.1:9650/ext/metrics") - getCallEnd := time.Now() - getCallDuration := getCallEnd.Sub(getCallStart) - - log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) - if err != nil { - return fmt.Errorf("failed getting metrics: %w", err) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("failed reading response body of metrics: %w", err) - } - - bodyString := string(body) - re := regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) - matches := re.FindAllStringSubmatch(bodyString, -1) - log.Info("Sum of time (in ns) of a build_block", "time", matches[len(matches)-1]) - - re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) - matches = re.FindAllStringSubmatch(bodyString, -1) - log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", matches[len(matches)-1]) - - re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) - matches = re.FindAllStringSubmatch(bodyString, -1) - log.Info("Sum of time (in ns) of a verify", "time", matches[len(matches)-1]) - - return nil -} From a3b60207cbcccfdbe2626dd67a26fff8c85b4770 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 29 Jun 2023 15:49:21 -0700 Subject: [PATCH 12/63] remove unused field --- cmd/simulator/txs/agent.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index beafce9929..776be9f535 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -35,10 +35,9 @@ type Agent[T any] interface { // issueNAgent issues and confirms a batch of N transactions at a time. type issueNAgent[T any] struct { - sequence TxSequence[T] - worker Worker[T] - n uint64 - blockchainIDStr string + sequence TxSequence[T] + worker Worker[T] + n uint64 } // NewIssueNAgent creates a new issueNAgent From c8f3da5e826aaf283659ca40cf2a464e2731f79d Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 08:50:08 -0700 Subject: [PATCH 13/63] revert file back --- cmd/simulator/load/funder.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index f360d5d259..995cae9203 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -21,7 +21,7 @@ import ( // DistributeFunds ensures that each address in keys has at least [minFundsPerAddr] by sending funds // from the key with the highest starting balance. // This function returns a set of at least [numKeys] keys, each having a minimum balance [minFundsPerAddr]. -func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int, blockchainID string) ([]*key.Key, error) { +func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int) ([]*key.Key, error) { if len(keys) < numKeys { return nil, fmt.Errorf("insufficient number of keys %d < %d", len(keys), numKeys) } @@ -107,7 +107,6 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K return nil, fmt.Errorf("failed to generate fund distribution sequence from %s of length %d", maxFundsKey.Address, len(needFundsAddrs)) } worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) - txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs) if err := txFunderAgent.Execute(ctx); err != nil { From 775e5e93bf9232ff158d9e9a70a5eecab9588412 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 08:55:43 -0700 Subject: [PATCH 14/63] cleaner --- cmd/simulator/load/loader.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 813158f484..d1e5ff360d 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -149,8 +149,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { func logOtherMetrics(blockchainIDStr string) error { getCallStart := time.Now() resp, err := http.Get("http://127.0.0.1:9650/ext/metrics") - getCallEnd := time.Now() - getCallDuration := getCallEnd.Sub(getCallStart) + getCallDuration := time.Since(getCallStart) log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) if err != nil { From ca504d35ff7e2a7ee3055327ad878f039b4ceffb Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 08:59:32 -0700 Subject: [PATCH 15/63] lint --- cmd/simulator/load/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index d1e5ff360d..d006b07982 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -75,7 +75,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { maxFeeCap := new(big.Int).Mul(big.NewInt(params.GWei), big.NewInt(config.MaxFeeCap)) minFundsPerAddr := new(big.Int).Mul(maxFeeCap, big.NewInt(int64(config.TxsPerWorker*params.TxGas))) log.Info("Distributing funds", "numTxsPerWorker", config.TxsPerWorker, "minFunds", minFundsPerAddr) - keys, err = DistributeFunds(ctx, clients[0], keys, config.Workers, minFundsPerAddr, blockchainIDStr) + keys, err = DistributeFunds(ctx, clients[0], keys, config.Workers, minFundsPerAddr) if err != nil { return err } From 7395f60923fc02d1b6087cb0a2c53c104c7e048c Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 09:29:27 -0700 Subject: [PATCH 16/63] make it work for ws or for rpc --- cmd/simulator/load/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index d006b07982..845b723b07 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -36,7 +36,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // Construct the arguments for the load simulator clients := make([]ethclient.Client, 0, len(config.Endpoints)) // Extract blockchainStrID from the clientURI - re := regexp.MustCompile(`bc\/(.*)\/ws`) + re := regexp.MustCompile(`bc\/(.*)\/`) matches := re.FindStringSubmatch(config.Endpoints[0]) if len(matches) < 1 { return fmt.Errorf("failed to get blockchainStrID from the clientURI %s", config.Endpoints[0]) From c9b96045eff89ae5a46ce1bb313966a201f0cf62 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 10:23:59 -0700 Subject: [PATCH 17/63] protect --- cmd/simulator/load/loader.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 845b723b07..f5a568fab4 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -35,14 +35,16 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // Construct the arguments for the load simulator clients := make([]ethclient.Client, 0, len(config.Endpoints)) - // Extract blockchainStrID from the clientURI + // Extract blockchainIDStr from the clientURI re := regexp.MustCompile(`bc\/(.*)\/`) matches := re.FindStringSubmatch(config.Endpoints[0]) if len(matches) < 1 { - return fmt.Errorf("failed to get blockchainStrID from the clientURI %s", config.Endpoints[0]) + return fmt.Errorf("failed to get blockchainIDStr from the clientURI %s", config.Endpoints[0]) } // Get the last element in matches blockchainIDStr := matches[len(matches)-1] + log.Info("Extracted blockchainIDStr from the clientURI", "blockchainIDStr", blockchainIDStr) + for i := 0; i < config.Workers; i++ { clientURI := config.Endpoints[i%len(config.Endpoints)] client, err := ethclient.Dial(clientURI) @@ -164,14 +166,26 @@ func logOtherMetrics(blockchainIDStr string) error { bodyString := string(body) re := regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) matches := re.FindAllStringSubmatch(bodyString, -1) + if len(matches) < 1 { + log.Info("No build_block metrics found from metrics API for blockchainIDStr %s", blockchainIDStr) + return nil + } log.Info("Sum of time (in ns) of a build_block", "time", matches[len(matches)-1]) re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) matches = re.FindAllStringSubmatch(bodyString, -1) + if len(matches) < 1 { + log.Info("No accepted_block metrics found from metrics API for blockchainIDStr %s", blockchainIDStr) + return nil + } log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", matches[len(matches)-1]) re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) matches = re.FindAllStringSubmatch(bodyString, -1) + if len(matches) < 1 { + log.Info("No verify metrics found from metrics API for blockchainIDStr %s", blockchainIDStr) + return nil + } log.Info("Sum of time (in ns) of a verify", "time", matches[len(matches)-1]) return nil From 35480f8528eaaf6fe9a5ae98243a367e3ebea606 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 10:48:39 -0700 Subject: [PATCH 18/63] endpoint --- cmd/simulator/load/loader.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index f5a568fab4..d1343ce07a 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -45,6 +45,15 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { blockchainIDStr := matches[len(matches)-1] log.Info("Extracted blockchainIDStr from the clientURI", "blockchainIDStr", blockchainIDStr) + re = regexp.MustCompile(`127.0.0.1:(.*)/ext/bc`) + matches = re.FindStringSubmatch(config.Endpoints[0]) + if len(matches) < 1 { + return fmt.Errorf("failed to get endpoint from the clientURI %s", config.Endpoints[0]) + } + // Get the last element in matches + endpoint := matches[len(matches)-1] + log.Info("Extracted endpoint from the clientURI", "endpoint", endpoint) + for i := 0; i < config.Workers; i++ { clientURI := config.Endpoints[i%len(config.Endpoints)] client, err := ethclient.Dial(clientURI) @@ -144,13 +153,14 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - logOtherMetrics(blockchainIDStr) + logOtherMetrics(blockchainIDStr, endpoint) return nil } -func logOtherMetrics(blockchainIDStr string) error { +func logOtherMetrics(blockchainIDStr string, endpoint string) error { getCallStart := time.Now() - resp, err := http.Get("http://127.0.0.1:9650/ext/metrics") + metricsAPI := fmt.Sprintf("http://127.0.0.1:%s/ext/metrics", endpoint) + resp, err := http.Get(metricsAPI) getCallDuration := time.Since(getCallStart) log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) @@ -167,7 +177,7 @@ func logOtherMetrics(blockchainIDStr string) error { re := regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) matches := re.FindAllStringSubmatch(bodyString, -1) if len(matches) < 1 { - log.Info("No build_block metrics found from metrics API for blockchainIDStr %s", blockchainIDStr) + log.Info("No build_block metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) return nil } log.Info("Sum of time (in ns) of a build_block", "time", matches[len(matches)-1]) @@ -175,7 +185,7 @@ func logOtherMetrics(blockchainIDStr string) error { re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) matches = re.FindAllStringSubmatch(bodyString, -1) if len(matches) < 1 { - log.Info("No accepted_block metrics found from metrics API for blockchainIDStr %s", blockchainIDStr) + log.Info("No accepted_block metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) return nil } log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", matches[len(matches)-1]) @@ -183,7 +193,7 @@ func logOtherMetrics(blockchainIDStr string) error { re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) matches = re.FindAllStringSubmatch(bodyString, -1) if len(matches) < 1 { - log.Info("No verify metrics found from metrics API for blockchainIDStr %s", blockchainIDStr) + log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) return nil } log.Info("Sum of time (in ns) of a verify", "time", matches[len(matches)-1]) From 867b81eda3f7f3c7d7e320d9be497885bae5cd78 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 11:25:35 -0700 Subject: [PATCH 19/63] no return on defer --- cmd/simulator/txs/agent.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 776be9f535..b339feafcc 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -65,8 +65,8 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { totalConfirmedTime time.Duration ) - defer func() error { - return a.worker.Close(ctx) + defer func() { + a.worker.Close(ctx) }() // Start time for execution From 4511cc53517d7c6405978a784d0b73e30ecee9f1 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 12:03:16 -0700 Subject: [PATCH 20/63] sep to a funciton --- cmd/simulator/load/loader.go | 38 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index d1343ce07a..f25ae6cbb8 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -6,6 +6,7 @@ package load import ( "context" "crypto/ecdsa" + "errors" "fmt" "io/ioutil" "math/big" @@ -174,29 +175,36 @@ func logOtherMetrics(blockchainIDStr string, endpoint string) error { } bodyString := string(body) - re := regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) - matches := re.FindAllStringSubmatch(bodyString, -1) - if len(matches) < 1 { - log.Info("No build_block metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) + + buildBlockTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) + if err != nil { + log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) return nil } - log.Info("Sum of time (in ns) of a build_block", "time", matches[len(matches)-1]) + log.Info("Sum of time (in ns) of a build_block", "time", buildBlockTime) - re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) - matches = re.FindAllStringSubmatch(bodyString, -1) - if len(matches) < 1 { - log.Info("No accepted_block metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) + issuedToAcceptedTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) + if err != nil { + log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) return nil } - log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", matches[len(matches)-1]) + log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", issuedToAcceptedTime) - re = regexp.MustCompile(fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) - matches = re.FindAllStringSubmatch(bodyString, -1) - if len(matches) < 1 { + verifyTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) + if err != nil { log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) return nil } - log.Info("Sum of time (in ns) of a verify", "time", matches[len(matches)-1]) - + log.Info("Sum of time (in ns) of a verify", "time", verifyTime) return nil } + +func findMatchFromString(fullString string, regex string) (string, error) { + re := regexp.MustCompile(regex) + matches := re.FindAllStringSubmatch(fullString, -1) + if len(matches) < 1 && len(matches[0]) < 1 { + return "", errors.New("could not find any matches for the given string") + } + + return matches[len(matches)-1][len(matches[0])-1], nil +} From 616d9c8e9ef3f809ce691698380c93f7e6b84928 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 12:33:03 -0700 Subject: [PATCH 21/63] have blockchainidstr passed in --- cmd/simulator/config/flags.go | 58 +++++++++++++++++++---------------- cmd/simulator/load/loader.go | 15 ++------- scripts/run_simulator.sh | 3 +- tests/load/load_test.go | 3 ++ 4 files changed, 39 insertions(+), 40 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index 70a227f61d..b7b6055b0f 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -16,17 +16,18 @@ import ( const Version = "v0.1.0" const ( - ConfigFilePathKey = "config-file" - LogLevelKey = "log-level" - EndpointsKey = "endpoints" - MaxFeeCapKey = "max-fee-cap" - MaxTipCapKey = "max-tip-cap" - WorkersKey = "workers" - TxsPerWorkerKey = "txs-per-worker" - KeyDirKey = "key-dir" - VersionKey = "version" - TimeoutKey = "timeout" - BatchSizeKey = "batch-size" + ConfigFilePathKey = "config-file" + LogLevelKey = "log-level" + EndpointsKey = "endpoints" + MaxFeeCapKey = "max-fee-cap" + MaxTipCapKey = "max-tip-cap" + WorkersKey = "workers" + TxsPerWorkerKey = "txs-per-worker" + KeyDirKey = "key-dir" + VersionKey = "version" + TimeoutKey = "timeout" + BatchSizeKey = "batch-size" + BlockchainIDStrKey = "blockchain-id-str" ) var ( @@ -36,26 +37,28 @@ var ( ) type Config struct { - Endpoints []string `json:"endpoints"` - MaxFeeCap int64 `json:"max-fee-cap"` - MaxTipCap int64 `json:"max-tip-cap"` - Workers int `json:"workers"` - TxsPerWorker uint64 `json:"txs-per-worker"` - KeyDir string `json:"key-dir"` - Timeout time.Duration `json:"timeout"` - BatchSize uint64 `json:"batch-size"` + Endpoints []string `json:"endpoints"` + MaxFeeCap int64 `json:"max-fee-cap"` + MaxTipCap int64 `json:"max-tip-cap"` + Workers int `json:"workers"` + TxsPerWorker uint64 `json:"txs-per-worker"` + KeyDir string `json:"key-dir"` + Timeout time.Duration `json:"timeout"` + BatchSize uint64 `json:"batch-size"` + BlockchainIDStr string `json:"blockchainIDStr"` } func BuildConfig(v *viper.Viper) (Config, error) { c := Config{ - Endpoints: v.GetStringSlice(EndpointsKey), - MaxFeeCap: v.GetInt64(MaxFeeCapKey), - MaxTipCap: v.GetInt64(MaxTipCapKey), - Workers: v.GetInt(WorkersKey), - TxsPerWorker: v.GetUint64(TxsPerWorkerKey), - KeyDir: v.GetString(KeyDirKey), - Timeout: v.GetDuration(TimeoutKey), - BatchSize: v.GetUint64(BatchSizeKey), + Endpoints: v.GetStringSlice(EndpointsKey), + MaxFeeCap: v.GetInt64(MaxFeeCapKey), + MaxTipCap: v.GetInt64(MaxTipCapKey), + Workers: v.GetInt(WorkersKey), + TxsPerWorker: v.GetUint64(TxsPerWorkerKey), + KeyDir: v.GetString(KeyDirKey), + Timeout: v.GetDuration(TimeoutKey), + BatchSize: v.GetUint64(BatchSizeKey), + BlockchainIDStr: v.GetString(BlockchainIDStrKey), } if len(c.Endpoints) == 0 { return c, ErrNoEndpoints @@ -118,4 +121,5 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") + fs.String(BlockchainIDStrKey, "C", "Specify the blockchainIDStr for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr") } diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index f25ae6cbb8..599be1c139 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -36,18 +36,9 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // Construct the arguments for the load simulator clients := make([]ethclient.Client, 0, len(config.Endpoints)) - // Extract blockchainIDStr from the clientURI - re := regexp.MustCompile(`bc\/(.*)\/`) - matches := re.FindStringSubmatch(config.Endpoints[0]) - if len(matches) < 1 { - return fmt.Errorf("failed to get blockchainIDStr from the clientURI %s", config.Endpoints[0]) - } - // Get the last element in matches - blockchainIDStr := matches[len(matches)-1] - log.Info("Extracted blockchainIDStr from the clientURI", "blockchainIDStr", blockchainIDStr) - re = regexp.MustCompile(`127.0.0.1:(.*)/ext/bc`) - matches = re.FindStringSubmatch(config.Endpoints[0]) + re := regexp.MustCompile(`127.0.0.1:(.*)/ext/bc`) + matches := re.FindStringSubmatch(config.Endpoints[0]) if len(matches) < 1 { return fmt.Errorf("failed to get endpoint from the clientURI %s", config.Endpoints[0]) } @@ -154,7 +145,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - logOtherMetrics(blockchainIDStr, endpoint) + logOtherMetrics(config.BlockchainIDStr, endpoint) return nil } diff --git a/scripts/run_simulator.sh b/scripts/run_simulator.sh index d1fb6c4c41..ef83df9ef8 100755 --- a/scripts/run_simulator.sh +++ b/scripts/run_simulator.sh @@ -36,7 +36,8 @@ run_simulator() { --timeout=30s \ --workers=1 \ --max-fee-cap=300 \ - --max-tip-cap=100 + --max-tip-cap=100 \ + --blockchain-id-str=$BLOCKCHAIN_ID } run_simulator diff --git a/tests/load/load_test.go b/tests/load/load_test.go index 19ddc3789e..ddb0758c9f 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -41,6 +41,9 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { err := os.Setenv("RPC_ENDPOINTS", commaSeparatedRPCEndpoints) gomega.Expect(err).Should(gomega.BeNil()) + err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) + gomega.Expect(err).Should(gomega.BeNil()) + log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints) cmd := exec.Command("./scripts/run_simulator.sh") log.Info("Running load simulator script", "cmd", cmd.String()) From 52622182a7a046be096d6cc6670ecf8449686158 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 12:51:25 -0700 Subject: [PATCH 22/63] typo --- cmd/simulator/load/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 599be1c139..a93e96584e 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -176,7 +176,7 @@ func logOtherMetrics(blockchainIDStr string, endpoint string) error { issuedToAcceptedTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) if err != nil { - log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) + log.Info("No issuedToAccepted metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) return nil } log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", issuedToAcceptedTime) From 46d120893acb6387ead6d176475c4c47ec5c14b5 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 13:13:29 -0700 Subject: [PATCH 23/63] pass in metrics through config --- cmd/simulator/config/flags.go | 4 ++++ cmd/simulator/load/loader.go | 32 ++++++++++++++++---------------- scripts/run_simulator.sh | 1 + tests/load/load_test.go | 8 +++++++- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index b7b6055b0f..00b9581efb 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -28,6 +28,7 @@ const ( TimeoutKey = "timeout" BatchSizeKey = "batch-size" BlockchainIDStrKey = "blockchain-id-str" + MetricsKey = "metrics" ) var ( @@ -46,6 +47,7 @@ type Config struct { Timeout time.Duration `json:"timeout"` BatchSize uint64 `json:"batch-size"` BlockchainIDStr string `json:"blockchainIDStr"` + Metrics string `json:"metrics"` } func BuildConfig(v *viper.Viper) (Config, error) { @@ -59,6 +61,7 @@ func BuildConfig(v *viper.Viper) (Config, error) { Timeout: v.GetDuration(TimeoutKey), BatchSize: v.GetUint64(BatchSizeKey), BlockchainIDStr: v.GetString(BlockchainIDStrKey), + Metrics: v.GetString(MetricsKey), } if len(c.Endpoints) == 0 { return c, ErrNoEndpoints @@ -122,4 +125,5 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") fs.String(BlockchainIDStrKey, "C", "Specify the blockchainIDStr for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr") + fs.String(MetricsKey, "http://127.0.0.1:9650/ext/metrics", "Specify the metrics endpoint for extra logging at the end of the simulation") } diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index a93e96584e..faed52c379 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -37,15 +37,6 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // Construct the arguments for the load simulator clients := make([]ethclient.Client, 0, len(config.Endpoints)) - re := regexp.MustCompile(`127.0.0.1:(.*)/ext/bc`) - matches := re.FindStringSubmatch(config.Endpoints[0]) - if len(matches) < 1 { - return fmt.Errorf("failed to get endpoint from the clientURI %s", config.Endpoints[0]) - } - // Get the last element in matches - endpoint := matches[len(matches)-1] - log.Info("Extracted endpoint from the clientURI", "endpoint", endpoint) - for i := 0; i < config.Workers; i++ { clientURI := config.Endpoints[i%len(config.Endpoints)] client, err := ethclient.Dial(clientURI) @@ -145,14 +136,23 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - logOtherMetrics(config.BlockchainIDStr, endpoint) + logOtherMetrics(config.Metrics, config.BlockchainIDStr) return nil } -func logOtherMetrics(blockchainIDStr string, endpoint string) error { +func logOtherMetrics(metrics string, blockchainIDStr string) error { + if metrics == "" { + log.Info("unable to get metrics: metrics is empty") + return nil + } + + if blockchainIDStr == "" { + log.Info("unable to get metrics: blockchainIDStr is empty") + return nil + } + getCallStart := time.Now() - metricsAPI := fmt.Sprintf("http://127.0.0.1:%s/ext/metrics", endpoint) - resp, err := http.Get(metricsAPI) + resp, err := http.Get(metrics) getCallDuration := time.Since(getCallStart) log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) @@ -169,21 +169,21 @@ func logOtherMetrics(blockchainIDStr string, endpoint string) error { buildBlockTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) if err != nil { - log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) + log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metric", metrics) return nil } log.Info("Sum of time (in ns) of a build_block", "time", buildBlockTime) issuedToAcceptedTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) if err != nil { - log.Info("No issuedToAccepted metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) + log.Info("No issuedToAccepted metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metrics", metrics) return nil } log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", issuedToAcceptedTime) verifyTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) if err != nil { - log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsAPI", metricsAPI) + log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "smetricsAPI", metrics) return nil } log.Info("Sum of time (in ns) of a verify", "time", verifyTime) diff --git a/scripts/run_simulator.sh b/scripts/run_simulator.sh index ef83df9ef8..15bebd8482 100755 --- a/scripts/run_simulator.sh +++ b/scripts/run_simulator.sh @@ -38,6 +38,7 @@ run_simulator() { --max-fee-cap=300 \ --max-tip-cap=100 \ --blockchain-id-str=$BLOCKCHAIN_ID + --metrics = $METRICS } run_simulator diff --git a/tests/load/load_test.go b/tests/load/load_test.go index ddb0758c9f..458b986aca 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -33,7 +33,10 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { blockchainID := subnetDetails.BlockchainID nodeURIs := subnetDetails.ValidatorURIs - rpcEndpoints := make([]string, 0, len(nodeURIs)) + nodeURIsLen := len(nodeURIs) + gomega.Expect(nodeURIsLen).Should(gomega.BeNumerically(">", 0)) + + rpcEndpoints := make([]string, 0, nodeURIsLen) for _, uri := range nodeURIs { rpcEndpoints = append(rpcEndpoints, fmt.Sprintf("%s/ext/bc/%s/rpc", uri, blockchainID)) } @@ -44,6 +47,9 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) gomega.Expect(err).Should(gomega.BeNil()) + err = os.Setenv("METRICS", fmt.Sprintf("%s/ext/metrics", nodeURIs[0])) + gomega.Expect(err).Should(gomega.BeNil()) + log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints) cmd := exec.Command("./scripts/run_simulator.sh") log.Info("Running load simulator script", "cmd", cmd.String()) From 6666a59faad11e1bd945f6df83deb47ccd362840 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 13:34:43 -0700 Subject: [PATCH 24/63] address comments --- cmd/simulator/config/flags.go | 68 +++++++++++++++++------------------ cmd/simulator/load/loader.go | 68 ++++++++++++++++++----------------- scripts/run_simulator.sh | 2 +- tests/load/load_test.go | 7 ++-- 4 files changed, 75 insertions(+), 70 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index 00b9581efb..8fb34efc65 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -16,19 +16,19 @@ import ( const Version = "v0.1.0" const ( - ConfigFilePathKey = "config-file" - LogLevelKey = "log-level" - EndpointsKey = "endpoints" - MaxFeeCapKey = "max-fee-cap" - MaxTipCapKey = "max-tip-cap" - WorkersKey = "workers" - TxsPerWorkerKey = "txs-per-worker" - KeyDirKey = "key-dir" - VersionKey = "version" - TimeoutKey = "timeout" - BatchSizeKey = "batch-size" - BlockchainIDStrKey = "blockchain-id-str" - MetricsKey = "metrics" + ConfigFilePathKey = "config-file" + LogLevelKey = "log-level" + EndpointsKey = "endpoints" + MaxFeeCapKey = "max-fee-cap" + MaxTipCapKey = "max-tip-cap" + WorkersKey = "workers" + TxsPerWorkerKey = "txs-per-worker" + KeyDirKey = "key-dir" + VersionKey = "version" + TimeoutKey = "timeout" + BatchSizeKey = "batch-size" + BlockchainIDStrKey = "blockchain-id-str" + MetricsEndpointsKey = "metrics-endpoints" ) var ( @@ -38,30 +38,30 @@ var ( ) type Config struct { - Endpoints []string `json:"endpoints"` - MaxFeeCap int64 `json:"max-fee-cap"` - MaxTipCap int64 `json:"max-tip-cap"` - Workers int `json:"workers"` - TxsPerWorker uint64 `json:"txs-per-worker"` - KeyDir string `json:"key-dir"` - Timeout time.Duration `json:"timeout"` - BatchSize uint64 `json:"batch-size"` - BlockchainIDStr string `json:"blockchainIDStr"` - Metrics string `json:"metrics"` + Endpoints []string `json:"endpoints"` + MaxFeeCap int64 `json:"max-fee-cap"` + MaxTipCap int64 `json:"max-tip-cap"` + Workers int `json:"workers"` + TxsPerWorker uint64 `json:"txs-per-worker"` + KeyDir string `json:"key-dir"` + Timeout time.Duration `json:"timeout"` + BatchSize uint64 `json:"batch-size"` + BlockchainIDStr string `json:"blockchainIDStr"` + MetricsEndpoints []string `json:"metrics-endpoints"` } func BuildConfig(v *viper.Viper) (Config, error) { c := Config{ - Endpoints: v.GetStringSlice(EndpointsKey), - MaxFeeCap: v.GetInt64(MaxFeeCapKey), - MaxTipCap: v.GetInt64(MaxTipCapKey), - Workers: v.GetInt(WorkersKey), - TxsPerWorker: v.GetUint64(TxsPerWorkerKey), - KeyDir: v.GetString(KeyDirKey), - Timeout: v.GetDuration(TimeoutKey), - BatchSize: v.GetUint64(BatchSizeKey), - BlockchainIDStr: v.GetString(BlockchainIDStrKey), - Metrics: v.GetString(MetricsKey), + Endpoints: v.GetStringSlice(EndpointsKey), + MaxFeeCap: v.GetInt64(MaxFeeCapKey), + MaxTipCap: v.GetInt64(MaxTipCapKey), + Workers: v.GetInt(WorkersKey), + TxsPerWorker: v.GetUint64(TxsPerWorkerKey), + KeyDir: v.GetString(KeyDirKey), + Timeout: v.GetDuration(TimeoutKey), + BatchSize: v.GetUint64(BatchSizeKey), + BlockchainIDStr: v.GetString(BlockchainIDStrKey), + MetricsEndpoints: v.GetStringSlice(MetricsEndpointsKey), } if len(c.Endpoints) == 0 { return c, ErrNoEndpoints @@ -125,5 +125,5 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") fs.String(BlockchainIDStrKey, "C", "Specify the blockchainIDStr for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr") - fs.String(MetricsKey, "http://127.0.0.1:9650/ext/metrics", "Specify the metrics endpoint for extra logging at the end of the simulation") + fs.StringSlice(MetricsEndpointsKey, []string{"http://127.0.0.1:9650/ext/metrics"}, "Specify a comma separated list of metric endpoints for extra logging at the end of the simulation (minimum of 1 endpoint)") } diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index faed52c379..6ca853300d 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -136,13 +136,13 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - logOtherMetrics(config.Metrics, config.BlockchainIDStr) + logExtraMetrics(config.MetricsEndpoints, config.BlockchainIDStr) return nil } -func logOtherMetrics(metrics string, blockchainIDStr string) error { - if metrics == "" { - log.Info("unable to get metrics: metrics is empty") +func logExtraMetrics(metricsEndpoints []string, blockchainIDStr string) error { + if len(metricsEndpoints) == 0 { + log.Info("unable to get metrics: metricEndpoints is empty") return nil } @@ -151,42 +151,44 @@ func logOtherMetrics(metrics string, blockchainIDStr string) error { return nil } - getCallStart := time.Now() - resp, err := http.Get(metrics) - getCallDuration := time.Since(getCallStart) + for i := 0; i < len(metricsEndpoints); i++ { + getCallStart := time.Now() + resp, err := http.Get(metricsEndpoints[i]) + getCallDuration := time.Since(getCallStart) - log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) - if err != nil { - return fmt.Errorf("failed getting metrics: %w", err) - } + log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) + if err != nil { + return fmt.Errorf("failed getting metrics: %w", err) + } - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("failed reading response body of metrics: %w", err) - } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("failed reading response body of metrics: %w", err) + } - bodyString := string(body) + bodyString := string(body) - buildBlockTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) - if err != nil { - log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metric", metrics) - return nil - } - log.Info("Sum of time (in ns) of a build_block", "time", buildBlockTime) + buildBlockTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) + if err != nil { + log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) + return nil + } + log.Info("Sum of time (in ns) of a build_block", "time", buildBlockTime) - issuedToAcceptedTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) - if err != nil { - log.Info("No issuedToAccepted metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metrics", metrics) - return nil - } - log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", issuedToAcceptedTime) + issuedToAcceptedTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) + if err != nil { + log.Info("No issuedToAccepted metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) + return nil + } + log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", issuedToAcceptedTime) - verifyTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) - if err != nil { - log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "smetricsAPI", metrics) - return nil + verifyTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) + if err != nil { + log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) + return nil + } + log.Info("Sum of time (in ns) of a verify", "time", verifyTime) } - log.Info("Sum of time (in ns) of a verify", "time", verifyTime) return nil } diff --git a/scripts/run_simulator.sh b/scripts/run_simulator.sh index 15bebd8482..9c3ad0982b 100755 --- a/scripts/run_simulator.sh +++ b/scripts/run_simulator.sh @@ -38,7 +38,7 @@ run_simulator() { --max-fee-cap=300 \ --max-tip-cap=100 \ --blockchain-id-str=$BLOCKCHAIN_ID - --metrics = $METRICS + --metrics=$METRICS_ENDPOINT } run_simulator diff --git a/tests/load/load_test.go b/tests/load/load_test.go index 458b986aca..132ef8caa4 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -37,17 +37,20 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { gomega.Expect(nodeURIsLen).Should(gomega.BeNumerically(">", 0)) rpcEndpoints := make([]string, 0, nodeURIsLen) + metricsEndpoints := make([]string, 0, nodeURIsLen) for _, uri := range nodeURIs { rpcEndpoints = append(rpcEndpoints, fmt.Sprintf("%s/ext/bc/%s/rpc", uri, blockchainID)) + metricsEndpoints = append(metricsEndpoints, fmt.Sprintf("%s/ext/metrics", uri)) } commaSeparatedRPCEndpoints := strings.Join(rpcEndpoints, ",") err := os.Setenv("RPC_ENDPOINTS", commaSeparatedRPCEndpoints) gomega.Expect(err).Should(gomega.BeNil()) - err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) + commaSeparatedMetricsEndpoints := strings.Join(metricsEndpoints, ",") + err = os.Setenv("METRICS_ENDPOINTS", commaSeparatedMetricsEndpoints) gomega.Expect(err).Should(gomega.BeNil()) - err = os.Setenv("METRICS", fmt.Sprintf("%s/ext/metrics", nodeURIs[0])) + err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) gomega.Expect(err).Should(gomega.BeNil()) log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints) From c30bf85a24e06ae16546efe275ff97c6017a17b3 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 13:45:41 -0700 Subject: [PATCH 25/63] address more comments and edit err policy of metrics functions --- cmd/simulator/load/loader.go | 14 ++++++-------- cmd/simulator/txs/agent.go | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 6ca853300d..ed4f2e863c 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -142,12 +142,12 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { func logExtraMetrics(metricsEndpoints []string, blockchainIDStr string) error { if len(metricsEndpoints) == 0 { - log.Info("unable to get metrics: metricEndpoints is empty") + log.Info("failed getting metrics: metricEndpoints is empty") return nil } if blockchainIDStr == "" { - log.Info("unable to get metrics: blockchainIDStr is empty") + log.Info("failed getting metrics: blockchainIDStr is empty") return nil } @@ -158,34 +158,32 @@ func logExtraMetrics(metricsEndpoints []string, blockchainIDStr string) error { log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) if err != nil { - return fmt.Errorf("failed getting metrics: %w", err) + log.Info("failed getting metrics", "err", err) + return nil } body, err := ioutil.ReadAll(resp.Body) if err != nil { - return fmt.Errorf("failed reading response body of metrics: %w", err) + log.Info("failed reading response body of metrics", "err", err) + return nil } bodyString := string(body) - buildBlockTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) if err != nil { log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) - return nil } log.Info("Sum of time (in ns) of a build_block", "time", buildBlockTime) issuedToAcceptedTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) if err != nil { log.Info("No issuedToAccepted metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) - return nil } log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", issuedToAcceptedTime) verifyTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) if err != nil { log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) - return nil } log.Info("Sum of time (in ns) of a verify", "time", verifyTime) } diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index b339feafcc..6a8d7d46ee 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -57,7 +57,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { txChan := a.sequence.Chan() confirmedCount := 0 - batchI := 1 + batchI := 0 // Tracks the total amount of time waiting for issuing and confirming txs var ( @@ -66,7 +66,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { ) defer func() { - a.worker.Close(ctx) + _ = a.worker.Close(ctx) }() // Start time for execution From 2048ffada2703f352c83705123dd8519a6db6a3b Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 13:58:51 -0700 Subject: [PATCH 26/63] add more logging to load_test --- tests/load/load_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/load/load_test.go b/tests/load/load_test.go index 132ef8caa4..00002a6dc2 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -53,7 +53,7 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) gomega.Expect(err).Should(gomega.BeNil()) - log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints) + log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints, commaSeparatedRPCEndpoints, blockchainID.String()) cmd := exec.Command("./scripts/run_simulator.sh") log.Info("Running load simulator script", "cmd", cmd.String()) From d7d09ff6c78b1aaee9495179d38b31f753ce5644 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 30 Jun 2023 14:11:24 -0700 Subject: [PATCH 27/63] typo --- tests/load/load_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/load/load_test.go b/tests/load/load_test.go index 00002a6dc2..d416d34f24 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -53,7 +53,7 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) gomega.Expect(err).Should(gomega.BeNil()) - log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints, commaSeparatedRPCEndpoints, blockchainID.String()) + log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints, "metricsEndpoints", commaSeparatedMetricsEndpoints, "blockchainIDStr", blockchainID.String()) cmd := exec.Command("./scripts/run_simulator.sh") log.Info("Running load simulator script", "cmd", cmd.String()) From 875048ef8d17bdfb1caaeffe4bbde6257f314e8f Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 3 Jul 2023 11:34:48 -0700 Subject: [PATCH 28/63] better check --- cmd/simulator/load/loader.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index ed4f2e863c..cb10e88bc9 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -193,9 +193,9 @@ func logExtraMetrics(metricsEndpoints []string, blockchainIDStr string) error { func findMatchFromString(fullString string, regex string) (string, error) { re := regexp.MustCompile(regex) matches := re.FindAllStringSubmatch(fullString, -1) - if len(matches) < 1 && len(matches[0]) < 1 { - return "", errors.New("could not find any matches for the given string") + if len(matches) > 0 && len(matches[0]) > 0 { + return matches[len(matches)-1][len(matches[0])-1], nil } - return matches[len(matches)-1][len(matches[0])-1], nil + return "", errors.New("could not find any matches for the given string") } From 59a2d298316e932b22c06108a792ecffd2657b93 Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 3 Jul 2023 11:45:52 -0700 Subject: [PATCH 29/63] fix endpoints --- scripts/run_simulator.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/run_simulator.sh b/scripts/run_simulator.sh index 9c3ad0982b..6e9c648124 100755 --- a/scripts/run_simulator.sh +++ b/scripts/run_simulator.sh @@ -37,8 +37,8 @@ run_simulator() { --workers=1 \ --max-fee-cap=300 \ --max-tip-cap=100 \ - --blockchain-id-str=$BLOCKCHAIN_ID - --metrics=$METRICS_ENDPOINT + --blockchain-id-str=$BLOCKCHAIN_ID \ + --metrics-endpoints=$METRICS_ENDPOINT } run_simulator From b07cfa9c375678fb56c7a9b70069076f71292618 Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 3 Jul 2023 12:28:46 -0700 Subject: [PATCH 30/63] typo: --- scripts/run_simulator.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run_simulator.sh b/scripts/run_simulator.sh index 6e9c648124..7d24d63d5b 100755 --- a/scripts/run_simulator.sh +++ b/scripts/run_simulator.sh @@ -38,7 +38,7 @@ run_simulator() { --max-fee-cap=300 \ --max-tip-cap=100 \ --blockchain-id-str=$BLOCKCHAIN_ID \ - --metrics-endpoints=$METRICS_ENDPOINT + --metrics-endpoints=$METRICS_ENDPOINTS } run_simulator From 710a222517744672ffd418efa65f20858ebb333e Mon Sep 17 00:00:00 2001 From: Anusha Date: Tue, 4 Jul 2023 15:09:21 -0700 Subject: [PATCH 31/63] individual --- cmd/simulator/load/funder.go | 2 +- cmd/simulator/load/loader.go | 2 +- cmd/simulator/load/worker.go | 22 +++++++++++++++++++--- cmd/simulator/txs/tx_generator.go | 30 ++++++++++++++++++++---------- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index 995cae9203..b49f25dad1 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -107,7 +107,7 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K return nil, fmt.Errorf("failed to generate fund distribution sequence from %s of length %d", maxFundsKey.Address, len(needFundsAddrs)) } worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) - txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs) + txFunderAgent := txs.NewIssueNAgent[txs.TimeTx](txSequence, worker, numTxs) if err := txFunderAgent.Execute(ctx); err != nil { return nil, err diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index cb10e88bc9..b8ca14d0b6 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -118,7 +118,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { log.Info("Constructing tx agents...", "numAgents", config.Workers) agents := make([]txs.Agent[*types.Transaction], 0, config.Workers) for i := 0; i < config.Workers; i++ { - agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) + agents = append(agents, txs.NewIssueNAgent[txs.TimeTx](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) } log.Info("Starting tx agents...") diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index adebc21922..777f82a297 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -8,6 +8,7 @@ import ( "fmt" "time" + "github.com/ava-labs/subnet-evm/cmd/simulator/txs" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/interfaces" @@ -44,16 +45,31 @@ func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, addr return tw } -func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, tx *types.Transaction) error { - return tw.client.SendTransaction(ctx, tx) +func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timeTx txs.TimeTx) error { + start := time.Now() + err := tw.client.SendTransaction(ctx, timeTx.Tx) + issuanceDuration := time.Since(start) + if err != nil { + return err + } + + timeTx.IssuanceStart = start + timeTx.IssuanceDuration = issuanceDuration + return nil } -func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, tx *types.Transaction) error { +func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timeTx txs.TimeTx) error { + tx := timeTx.Tx txNonce := tx.Nonce() + start := time.Now() for { // If the is less than what has already been accepted, the transaction is confirmed if txNonce < tw.acceptedNonce { + confirmationEnd := time.Now() + timeTx.ConfirmationDuration = start.Sub(confirmationEnd) + timeTx.IssuanceToConfirmationDuration = timeTx.IssuanceStart.Sub(confirmationEnd) + log.Info("Individual Tx Time", "Issuance to Confirmation", timeTx.IssuanceToConfirmationDuration) return nil } diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index 85b5e2fe59..4a95adab25 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -7,36 +7,46 @@ import ( "context" "crypto/ecdsa" "fmt" + "time" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" ethcrypto "github.com/ethereum/go-ethereum/crypto" ) -var _ TxSequence[*types.Transaction] = (*txSequence)(nil) +var _ TxSequence[TimeTx] = (*txSequence)(nil) type CreateTx func(key *ecdsa.PrivateKey, nonce uint64) (*types.Transaction, error) +type TimeTx struct { + Tx *types.Transaction + IssuanceDuration time.Duration + ConfirmationDuration time.Duration + IssuanceStart time.Time + IssuanceToConfirmationDuration time.Duration +} + // GenerateTxSequence fetches the current nonce of key and calls [generator] [numTxs] times sequentially to generate a sequence of transactions. -func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclient.Client, key *ecdsa.PrivateKey, numTxs uint64) (TxSequence[*types.Transaction], error) { +func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclient.Client, key *ecdsa.PrivateKey, numTxs uint64) (TxSequence[TimeTx], error) { address := ethcrypto.PubkeyToAddress(key.PublicKey) startingNonce, err := client.NonceAt(ctx, address, nil) if err != nil { return nil, fmt.Errorf("failed to fetch nonce for address %s: %w", address, err) } - txs := make([]*types.Transaction, 0, numTxs) + txs := make([]TimeTx, 0, numTxs) for i := uint64(0); i < numTxs; i++ { tx, err := generator(key, startingNonce+i) if err != nil { return nil, fmt.Errorf("failed to sign tx at index %d: %w", i, err) } - txs = append(txs, tx) + timeTx := TimeTx{Tx: tx} + txs = append(txs, timeTx) } return ConvertTxSliceToSequence(txs), nil } -func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[*types.Transaction], error) { - txSequences := make([]TxSequence[*types.Transaction], len(keys)) +func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[TimeTx], error) { + txSequences := make([]TxSequence[TimeTx], len(keys)) for i, key := range keys { txs, err := GenerateTxSequence(ctx, generator, client, key, txsPerKey) if err != nil { @@ -48,11 +58,11 @@ func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclie } type txSequence struct { - txChan chan *types.Transaction + txChan chan TimeTx } -func ConvertTxSliceToSequence(txs []*types.Transaction) TxSequence[*types.Transaction] { - txChan := make(chan *types.Transaction, len(txs)) +func ConvertTxSliceToSequence(txs []TimeTx) TxSequence[TimeTx] { + txChan := make(chan TimeTx, len(txs)) for _, tx := range txs { txChan <- tx } @@ -63,6 +73,6 @@ func ConvertTxSliceToSequence(txs []*types.Transaction) TxSequence[*types.Transa } } -func (t *txSequence) Chan() <-chan *types.Transaction { +func (t *txSequence) Chan() <-chan TimeTx { return t.txChan } From 63731b77fa7994977f4990832c62583416490814 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 6 Jul 2023 14:00:16 -0700 Subject: [PATCH 32/63] histogram --- cmd/simulator/load/worker.go | 39 +++++++++++++++++++++++++++++++++--- cmd/simulator/txs/agent.go | 4 ++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index 777f82a297..ceae4fea89 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -6,12 +6,14 @@ package load import ( "context" "fmt" + "os" "time" "github.com/ava-labs/subnet-evm/cmd/simulator/txs" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/interfaces" + "github.com/aybabtme/uniplot/histogram" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -24,6 +26,10 @@ type singleAddressTxWorker struct { sub interfaces.Subscription newHeads chan *types.Header + + issuanceToConfirmationHistogram []float64 + confirmationHistogram []float64 + issuanceHistogram []float64 } // NewSingleAddressTxWorker creates and returns a singleAddressTxWorker @@ -55,6 +61,7 @@ func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timeTx txs.TimeTx) timeTx.IssuanceStart = start timeTx.IssuanceDuration = issuanceDuration + tw.issuanceHistogram = append(tw.issuanceHistogram, timeTx.IssuanceDuration.Seconds()) return nil } @@ -67,9 +74,11 @@ func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timeTx txs.TimeT // If the is less than what has already been accepted, the transaction is confirmed if txNonce < tw.acceptedNonce { confirmationEnd := time.Now() - timeTx.ConfirmationDuration = start.Sub(confirmationEnd) - timeTx.IssuanceToConfirmationDuration = timeTx.IssuanceStart.Sub(confirmationEnd) - log.Info("Individual Tx Time", "Issuance to Confirmation", timeTx.IssuanceToConfirmationDuration) + timeTx.ConfirmationDuration = confirmationEnd.Sub(start) + timeTx.IssuanceToConfirmationDuration = confirmationEnd.Sub(timeTx.IssuanceStart) + tw.issuanceToConfirmationHistogram = append(tw.issuanceToConfirmationHistogram, timeTx.IssuanceToConfirmationDuration.Seconds()) + tw.confirmationHistogram = append(tw.confirmationHistogram, timeTx.ConfirmationDuration.Seconds()) + return nil } @@ -97,3 +106,27 @@ func (tw *singleAddressTxWorker) Close(ctx context.Context) error { close(tw.newHeads) return nil } + +func (tw *singleAddressTxWorker) CollectMetrics(ctx context.Context) error { + log.Info("Individual Tx Issuance to Confirmation Duration Histogram (s)") + hist := histogram.Hist(10, tw.issuanceToConfirmationHistogram) + err := histogram.Fprint(os.Stdout, hist, histogram.Linear(5)) + if err != nil { + return err + } + + log.Info("Individual Tx Issuance Histogram (s)") + hist = histogram.Hist(10, tw.issuanceHistogram) + err = histogram.Fprint(os.Stdout, hist, histogram.Linear(5)) + if err != nil { + return err + } + + log.Info("Individual Tx Confirmation (s)") + hist = histogram.Hist(10, tw.confirmationHistogram) + err = histogram.Fprint(os.Stdout, hist, histogram.Linear(5)) + if err != nil { + return err + } + return nil +} diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 6a8d7d46ee..e111b0114c 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -26,6 +26,7 @@ type Worker[T any] interface { IssueTx(ctx context.Context, tx T) error ConfirmTx(ctx context.Context, tx T) error Close(ctx context.Context) error + CollectMetrics(ctx context.Context) error } // Execute the work of the given agent. @@ -117,6 +118,9 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { totalTime := time.Since(start).Seconds() log.Info("Execution complete", "totalTxs", confirmedCount, "totalTime", totalTime, "TPS", float64(confirmedCount)/totalTime, "issuanceTime", totalIssuedTime.Seconds(), "confirmedTime", totalConfirmedTime.Seconds()) + if err := a.worker.CollectMetrics(ctx); err != nil { + return fmt.Errorf("failed collect metrics: %w", err) + } return nil } From 9821242a227124d1fa5e94e34ac41273edc46baf Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 6 Jul 2023 14:58:39 -0700 Subject: [PATCH 33/63] address feedback: --- cmd/simulator/config/flags.go | 2 +- go.mod | 1 + go.sum | 2 ++ tests/load/load_test.go | 3 +-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index 8fb34efc65..0eea9d8b52 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -124,6 +124,6 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") - fs.String(BlockchainIDStrKey, "C", "Specify the blockchainIDStr for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr") + fs.String(BlockchainIDStrKey, "C", "Specify the blockchainIDStr for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr (full 32 byte hash blockchainID)") fs.StringSlice(MetricsEndpointsKey, []string{"http://127.0.0.1:9650/ext/metrics"}, "Specify a comma separated list of metric endpoints for extra logging at the end of the simulation (minimum of 1 endpoint)") } diff --git a/go.mod b/go.mod index b3bbb63dc7..43145461e1 100644 --- a/go.mod +++ b/go.mod @@ -53,6 +53,7 @@ require ( github.com/Microsoft/go-winio v0.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/ava-labs/coreth v0.12.2-rc.0 // indirect + github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect diff --git a/go.sum b/go.sum index ef10eee19e..71e7953eca 100644 --- a/go.sum +++ b/go.sum @@ -69,6 +69,8 @@ github.com/ava-labs/avalanchego v1.10.2 h1:kDM2xfQDaewueUCxJUujPlbNQ91gtJfXY9Z0C github.com/ava-labs/avalanchego v1.10.2/go.mod h1:PsNLfOc9FnsnoJ8CjauclvFy6BCSVZmT05I4c9rm4a4= github.com/ava-labs/coreth v0.12.2-rc.0 h1:nGhGN4bYqid5EgqH/GFky2ybY8bGRxto6Bo7nes1V+Y= github.com/ava-labs/coreth v0.12.2-rc.0/go.mod h1:/5x54QlIKjlPebkdzTA5ic9wXdejbWOnQosztkv9jxo= +github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e h1:dSeuFcs4WAJJnswS8vXy7YY1+fdlbVPuEVmDAfqvFOQ= +github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e/go.mod h1:uh71c5Vc3VNIplXOFXsnDy21T1BepgT32c5X/YPrOyc= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= diff --git a/tests/load/load_test.go b/tests/load/load_test.go index d416d34f24..dfb12ea93c 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -34,7 +34,6 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { nodeURIs := subnetDetails.ValidatorURIs nodeURIsLen := len(nodeURIs) - gomega.Expect(nodeURIsLen).Should(gomega.BeNumerically(">", 0)) rpcEndpoints := make([]string, 0, nodeURIsLen) metricsEndpoints := make([]string, 0, nodeURIsLen) @@ -53,7 +52,7 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) gomega.Expect(err).Should(gomega.BeNil()) - log.Info("Sleeping with network running", "rpcEndpoints", commaSeparatedRPCEndpoints, "metricsEndpoints", commaSeparatedMetricsEndpoints, "blockchainIDStr", blockchainID.String()) + log.Info("Running load simulator...", "rpcEndpoints", commaSeparatedRPCEndpoints, "metricsEndpoints", commaSeparatedMetricsEndpoints, "blockchainIDStr", blockchainID.String()) cmd := exec.Command("./scripts/run_simulator.sh") log.Info("Running load simulator script", "cmd", cmd.String()) From 2ad7ad39a0bbcc8a356cb9e3d1580f8480bcae32 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 6 Jul 2023 15:14:41 -0700 Subject: [PATCH 34/63] remove metrics from default --- cmd/simulator/config/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index 0eea9d8b52..fccb106fa1 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -125,5 +125,5 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") fs.String(BlockchainIDStrKey, "C", "Specify the blockchainIDStr for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr (full 32 byte hash blockchainID)") - fs.StringSlice(MetricsEndpointsKey, []string{"http://127.0.0.1:9650/ext/metrics"}, "Specify a comma separated list of metric endpoints for extra logging at the end of the simulation (minimum of 1 endpoint)") + fs.StringSlice(MetricsEndpointsKey, []string{}, "Specify a comma separated list of metric endpoints for extra logging at the end of the simulation (minimum of 1 endpoint)") } From 649daca1224bcdf15b3bd587a64af43558e57efa Mon Sep 17 00:00:00 2001 From: Anusha Date: Tue, 11 Jul 2023 10:09:48 -0700 Subject: [PATCH 35/63] address comments --- cmd/simulator/config/flags.go | 4 ++-- cmd/simulator/load/funder.go | 2 +- cmd/simulator/load/loader.go | 2 +- cmd/simulator/load/worker.go | 24 ++++++++++++------------ cmd/simulator/txs/tx_generator.go | 24 ++++++++++++------------ go.mod | 2 +- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index fccb106fa1..2175955168 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -46,7 +46,7 @@ type Config struct { KeyDir string `json:"key-dir"` Timeout time.Duration `json:"timeout"` BatchSize uint64 `json:"batch-size"` - BlockchainIDStr string `json:"blockchainIDStr"` + BlockchainIDStr string `json:"blockchain-id-str"` MetricsEndpoints []string `json:"metrics-endpoints"` } @@ -124,6 +124,6 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") - fs.String(BlockchainIDStrKey, "C", "Specify the blockchainIDStr for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr (full 32 byte hash blockchainID)") + fs.String(BlockchainIDStrKey, "C", "Specify the blockchain ID for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr (full 32 byte hash blockchainID)") fs.StringSlice(MetricsEndpointsKey, []string{}, "Specify a comma separated list of metric endpoints for extra logging at the end of the simulation (minimum of 1 endpoint)") } diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index b49f25dad1..7e3e0a1e0f 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -107,7 +107,7 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K return nil, fmt.Errorf("failed to generate fund distribution sequence from %s of length %d", maxFundsKey.Address, len(needFundsAddrs)) } worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) - txFunderAgent := txs.NewIssueNAgent[txs.TimeTx](txSequence, worker, numTxs) + txFunderAgent := txs.NewIssueNAgent[txs.TimedTx](txSequence, worker, numTxs) if err := txFunderAgent.Execute(ctx); err != nil { return nil, err diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index b8ca14d0b6..ab7075eb94 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -118,7 +118,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { log.Info("Constructing tx agents...", "numAgents", config.Workers) agents := make([]txs.Agent[*types.Transaction], 0, config.Workers) for i := 0; i < config.Workers; i++ { - agents = append(agents, txs.NewIssueNAgent[txs.TimeTx](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) + agents = append(agents, txs.NewIssueNAgent[txs.TimedTx](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) } log.Info("Starting tx agents...") diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index ceae4fea89..ade488ee5a 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -51,22 +51,22 @@ func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, addr return tw } -func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timeTx txs.TimeTx) error { +func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timedTx txs.TimedTx) error { start := time.Now() - err := tw.client.SendTransaction(ctx, timeTx.Tx) - issuanceDuration := time.Since(start) + err := tw.client.SendTransaction(ctx, timedTx.Tx) if err != nil { return err } + issuanceDuration := time.Since(start) - timeTx.IssuanceStart = start - timeTx.IssuanceDuration = issuanceDuration - tw.issuanceHistogram = append(tw.issuanceHistogram, timeTx.IssuanceDuration.Seconds()) + timedTx.IssuanceStart = start + timedTx.IssuanceDuration = issuanceDuration + tw.issuanceHistogram = append(tw.issuanceHistogram, timedTx.IssuanceDuration.Seconds()) return nil } -func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timeTx txs.TimeTx) error { - tx := timeTx.Tx +func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timedTx txs.TimedTx) error { + tx := timedTx.Tx txNonce := tx.Nonce() start := time.Now() @@ -74,10 +74,10 @@ func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timeTx txs.TimeT // If the is less than what has already been accepted, the transaction is confirmed if txNonce < tw.acceptedNonce { confirmationEnd := time.Now() - timeTx.ConfirmationDuration = confirmationEnd.Sub(start) - timeTx.IssuanceToConfirmationDuration = confirmationEnd.Sub(timeTx.IssuanceStart) - tw.issuanceToConfirmationHistogram = append(tw.issuanceToConfirmationHistogram, timeTx.IssuanceToConfirmationDuration.Seconds()) - tw.confirmationHistogram = append(tw.confirmationHistogram, timeTx.ConfirmationDuration.Seconds()) + timedTx.ConfirmationDuration = confirmationEnd.Sub(start) + timedTx.IssuanceToConfirmationDuration = confirmationEnd.Sub(timedTx.IssuanceStart) + tw.issuanceToConfirmationHistogram = append(tw.issuanceToConfirmationHistogram, timedTx.IssuanceToConfirmationDuration.Seconds()) + tw.confirmationHistogram = append(tw.confirmationHistogram, timedTx.ConfirmationDuration.Seconds()) return nil } diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index 4a95adab25..dcde2ef348 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -14,11 +14,11 @@ import ( ethcrypto "github.com/ethereum/go-ethereum/crypto" ) -var _ TxSequence[TimeTx] = (*txSequence)(nil) +var _ TxSequence[TimedTx] = (*txSequence)(nil) type CreateTx func(key *ecdsa.PrivateKey, nonce uint64) (*types.Transaction, error) -type TimeTx struct { +type TimedTx struct { Tx *types.Transaction IssuanceDuration time.Duration ConfirmationDuration time.Duration @@ -27,26 +27,26 @@ type TimeTx struct { } // GenerateTxSequence fetches the current nonce of key and calls [generator] [numTxs] times sequentially to generate a sequence of transactions. -func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclient.Client, key *ecdsa.PrivateKey, numTxs uint64) (TxSequence[TimeTx], error) { +func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclient.Client, key *ecdsa.PrivateKey, numTxs uint64) (TxSequence[TimedTx], error) { address := ethcrypto.PubkeyToAddress(key.PublicKey) startingNonce, err := client.NonceAt(ctx, address, nil) if err != nil { return nil, fmt.Errorf("failed to fetch nonce for address %s: %w", address, err) } - txs := make([]TimeTx, 0, numTxs) + txs := make([]TimedTx, 0, numTxs) for i := uint64(0); i < numTxs; i++ { tx, err := generator(key, startingNonce+i) if err != nil { return nil, fmt.Errorf("failed to sign tx at index %d: %w", i, err) } - timeTx := TimeTx{Tx: tx} - txs = append(txs, timeTx) + timedTx := TimedTx{Tx: tx} + txs = append(txs, timedTx) } return ConvertTxSliceToSequence(txs), nil } -func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[TimeTx], error) { - txSequences := make([]TxSequence[TimeTx], len(keys)) +func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[TimedTx], error) { + txSequences := make([]TxSequence[TimedTx], len(keys)) for i, key := range keys { txs, err := GenerateTxSequence(ctx, generator, client, key, txsPerKey) if err != nil { @@ -58,11 +58,11 @@ func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclie } type txSequence struct { - txChan chan TimeTx + txChan chan TimedTx } -func ConvertTxSliceToSequence(txs []TimeTx) TxSequence[TimeTx] { - txChan := make(chan TimeTx, len(txs)) +func ConvertTxSliceToSequence(txs []TimedTx) TxSequence[TimedTx] { + txChan := make(chan TimedTx, len(txs)) for _, tx := range txs { txChan <- tx } @@ -73,6 +73,6 @@ func ConvertTxSliceToSequence(txs []TimeTx) TxSequence[TimeTx] { } } -func (t *txSequence) Chan() <-chan TimeTx { +func (t *txSequence) Chan() <-chan TimedTx { return t.txChan } diff --git a/go.mod b/go.mod index 43145461e1..aadb152c27 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/VictoriaMetrics/fastcache v1.10.0 github.com/ava-labs/avalanche-network-runner v1.6.0 github.com/ava-labs/avalanchego v1.10.2 + github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e github.com/cespare/cp v0.1.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 @@ -53,7 +54,6 @@ require ( github.com/Microsoft/go-winio v0.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/ava-labs/coreth v0.12.2-rc.0 // indirect - github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect From 2ffda7a22327621a2ee94eeb91f464bcdc952743 Mon Sep 17 00:00:00 2001 From: Anusha Date: Tue, 11 Jul 2023 10:17:04 -0700 Subject: [PATCH 36/63] simplify time metrics --- cmd/simulator/load/worker.go | 5 ++--- cmd/simulator/txs/tx_generator.go | 8 +++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index ade488ee5a..399411c002 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -59,7 +59,6 @@ func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timedTx txs.TimedT } issuanceDuration := time.Since(start) - timedTx.IssuanceStart = start timedTx.IssuanceDuration = issuanceDuration tw.issuanceHistogram = append(tw.issuanceHistogram, timedTx.IssuanceDuration.Seconds()) return nil @@ -75,8 +74,8 @@ func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timedTx txs.Time if txNonce < tw.acceptedNonce { confirmationEnd := time.Now() timedTx.ConfirmationDuration = confirmationEnd.Sub(start) - timedTx.IssuanceToConfirmationDuration = confirmationEnd.Sub(timedTx.IssuanceStart) - tw.issuanceToConfirmationHistogram = append(tw.issuanceToConfirmationHistogram, timedTx.IssuanceToConfirmationDuration.Seconds()) + issuanceToConfirmationDuration := timedTx.IssuanceDuration + timedTx.ConfirmationDuration + tw.issuanceToConfirmationHistogram = append(tw.issuanceToConfirmationHistogram, issuanceToConfirmationDuration.Seconds()) tw.confirmationHistogram = append(tw.confirmationHistogram, timedTx.ConfirmationDuration.Seconds()) return nil diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index dcde2ef348..6bb1755b8e 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -19,11 +19,9 @@ var _ TxSequence[TimedTx] = (*txSequence)(nil) type CreateTx func(key *ecdsa.PrivateKey, nonce uint64) (*types.Transaction, error) type TimedTx struct { - Tx *types.Transaction - IssuanceDuration time.Duration - ConfirmationDuration time.Duration - IssuanceStart time.Time - IssuanceToConfirmationDuration time.Duration + Tx *types.Transaction + IssuanceDuration time.Duration + ConfirmationDuration time.Duration } // GenerateTxSequence fetches the current nonce of key and calls [generator] [numTxs] times sequentially to generate a sequence of transactions. From e4fb3320312b0e63201a528cf809993b4d55c618 Mon Sep 17 00:00:00 2001 From: Anusha Date: Tue, 11 Jul 2023 10:40:09 -0700 Subject: [PATCH 37/63] better explanation --- cmd/simulator/load/loader.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index ab7075eb94..38160b7bec 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -193,8 +193,11 @@ func logExtraMetrics(metricsEndpoints []string, blockchainIDStr string) error { func findMatchFromString(fullString string, regex string) (string, error) { re := regexp.MustCompile(regex) matches := re.FindAllStringSubmatch(fullString, -1) - if len(matches) > 0 && len(matches[0]) > 0 { - return matches[len(matches)-1][len(matches[0])-1], nil + if len(matches) > 0 && len(matches[len(matches)-1]) > 0 { + // This is hardcoded for the metrics API. + // We know the exact metric we want will always be the last item in the + // 2D slice which only has one item. + return matches[len(matches)-1][0], nil } return "", errors.New("could not find any matches for the given string") From 8849b75dcf03b58df02dcaeaf87d81a7fa003b62 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 09:18:31 -0700 Subject: [PATCH 38/63] address comments --- cmd/simulator/config/flags.go | 2 +- cmd/simulator/load/worker.go | 42 -------------------------------- cmd/simulator/metrics/metrics.go | 31 +++++++++++++++++++++++ cmd/simulator/txs/agent.go | 26 +++++++++++++++----- 4 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 cmd/simulator/metrics/metrics.go diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index 2175955168..a880fbd8c3 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -13,7 +13,7 @@ import ( "github.com/spf13/viper" ) -const Version = "v0.1.0" +const Version = "v0.1.1" const ( ConfigFilePathKey = "config-file" diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index 399411c002..911645f013 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -6,14 +6,12 @@ package load import ( "context" "fmt" - "os" "time" "github.com/ava-labs/subnet-evm/cmd/simulator/txs" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/interfaces" - "github.com/aybabtme/uniplot/histogram" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -26,10 +24,6 @@ type singleAddressTxWorker struct { sub interfaces.Subscription newHeads chan *types.Header - - issuanceToConfirmationHistogram []float64 - confirmationHistogram []float64 - issuanceHistogram []float64 } // NewSingleAddressTxWorker creates and returns a singleAddressTxWorker @@ -52,15 +46,11 @@ func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, addr } func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timedTx txs.TimedTx) error { - start := time.Now() err := tw.client.SendTransaction(ctx, timedTx.Tx) if err != nil { return err } - issuanceDuration := time.Since(start) - timedTx.IssuanceDuration = issuanceDuration - tw.issuanceHistogram = append(tw.issuanceHistogram, timedTx.IssuanceDuration.Seconds()) return nil } @@ -68,16 +58,8 @@ func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timedTx txs.Time tx := timedTx.Tx txNonce := tx.Nonce() - start := time.Now() for { - // If the is less than what has already been accepted, the transaction is confirmed if txNonce < tw.acceptedNonce { - confirmationEnd := time.Now() - timedTx.ConfirmationDuration = confirmationEnd.Sub(start) - issuanceToConfirmationDuration := timedTx.IssuanceDuration + timedTx.ConfirmationDuration - tw.issuanceToConfirmationHistogram = append(tw.issuanceToConfirmationHistogram, issuanceToConfirmationDuration.Seconds()) - tw.confirmationHistogram = append(tw.confirmationHistogram, timedTx.ConfirmationDuration.Seconds()) - return nil } @@ -105,27 +87,3 @@ func (tw *singleAddressTxWorker) Close(ctx context.Context) error { close(tw.newHeads) return nil } - -func (tw *singleAddressTxWorker) CollectMetrics(ctx context.Context) error { - log.Info("Individual Tx Issuance to Confirmation Duration Histogram (s)") - hist := histogram.Hist(10, tw.issuanceToConfirmationHistogram) - err := histogram.Fprint(os.Stdout, hist, histogram.Linear(5)) - if err != nil { - return err - } - - log.Info("Individual Tx Issuance Histogram (s)") - hist = histogram.Hist(10, tw.issuanceHistogram) - err = histogram.Fprint(os.Stdout, hist, histogram.Linear(5)) - if err != nil { - return err - } - - log.Info("Individual Tx Confirmation (s)") - hist = histogram.Hist(10, tw.confirmationHistogram) - err = histogram.Fprint(os.Stdout, hist, histogram.Linear(5)) - if err != nil { - return err - } - return nil -} diff --git a/cmd/simulator/metrics/metrics.go b/cmd/simulator/metrics/metrics.go new file mode 100644 index 0000000000..a238c245c3 --- /dev/null +++ b/cmd/simulator/metrics/metrics.go @@ -0,0 +1,31 @@ +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +type metrics struct { + // Summary of the quantiles of Individual Confirmation Tx Times + ConfirmationTxTimes prometheus.Summary + // Summary of the quantiles of Individual Issuance Tx Times + IssuanceTxTimes prometheus.Summary +} + +// NewMetrics creates and returns a metrics and registers it with a Collector +func NewMetrics(reg prometheus.Registerer) *metrics { + m := &metrics{ + ConfirmationTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ + Name: "confirmation_tx_times", + Help: "Individual Tx Confirmation Times for a Load Test", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, + }), + IssuanceTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ + Name: "issuance_tx_times", + Help: "Individual Tx Issuance Times for a Load Test", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, + }), + } + reg.MustRegister(m.ConfirmationTxTimes) + reg.MustRegister(m.IssuanceTxTimes) + return m +} diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index e111b0114c..6836d3dee2 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -7,9 +7,13 @@ import ( "context" "errors" "fmt" + "net/http" "time" + "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" "github.com/ethereum/go-ethereum/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" ) // TxSequence provides an interface to return a channel of transactions. @@ -26,7 +30,6 @@ type Worker[T any] interface { IssueTx(ctx context.Context, tx T) error ConfirmTx(ctx context.Context, tx T) error Close(ctx context.Context) error - CollectMetrics(ctx context.Context) error } // Execute the work of the given agent. @@ -60,6 +63,9 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { confirmedCount := 0 batchI := 0 + reg := prometheus.NewRegistry() + m := metrics.NewMetrics(reg) + // Tracks the total amount of time waiting for issuing and confirming txs var ( totalIssuedTime time.Duration @@ -67,7 +73,9 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { ) defer func() { - _ = a.worker.Close(ctx) + if err := a.worker.Close(ctx); err != nil { + log.Error("error trying to close worker: %w", "err", err) + } }() // Start time for execution @@ -89,9 +97,12 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { if !moreTxs { break L } + start := time.Now() if err := a.worker.IssueTx(ctx, tx); err != nil { return fmt.Errorf("failed to issue transaction %d: %w", len(txs), err) } + issuanceTime := time.Since(start) + m.IssuanceTxTimes.Observe(issuanceTime.Seconds()) txs = append(txs, tx) } } @@ -103,9 +114,12 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { // Wait for txs in this batch to confirm confirmedStart := time.Now() for i, tx := range txs { + start := time.Now() if err := a.worker.ConfirmTx(ctx, tx); err != nil { return fmt.Errorf("failed to await transaction %d: %w", i, err) } + confirmationTime := time.Since(start) + m.ConfirmationTxTimes.Observe(confirmationTime.Seconds()) confirmedCount++ } // Get the batch's confirmation time and add it to totalConfirmedTime @@ -118,10 +132,10 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { totalTime := time.Since(start).Seconds() log.Info("Execution complete", "totalTxs", confirmedCount, "totalTime", totalTime, "TPS", float64(confirmedCount)/totalTime, "issuanceTime", totalIssuedTime.Seconds(), "confirmedTime", totalConfirmedTime.Seconds()) - if err := a.worker.CollectMetrics(ctx); err != nil { - return fmt.Errorf("failed collect metrics: %w", err) - } - return nil + + // Start a prometheus server to expose individual tx metrics + http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) + log.Error("Listen", "err", http.ListenAndServe(":8082", nil)) } batchI++ From 8e7bbdc72e3857c9686faf1526b7248ee90ad365 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 11:14:35 -0700 Subject: [PATCH 39/63] address comments --- cmd/simulator/config/flags.go | 62 +++++++++++-------------- cmd/simulator/load/funder.go | 7 ++- cmd/simulator/load/loader.go | 80 +++++--------------------------- cmd/simulator/metrics/metrics.go | 8 ++-- cmd/simulator/txs/agent.go | 14 ++---- tests/load/load_test.go | 11 +---- 6 files changed, 52 insertions(+), 130 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index a880fbd8c3..4931ee1a1f 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -16,19 +16,17 @@ import ( const Version = "v0.1.1" const ( - ConfigFilePathKey = "config-file" - LogLevelKey = "log-level" - EndpointsKey = "endpoints" - MaxFeeCapKey = "max-fee-cap" - MaxTipCapKey = "max-tip-cap" - WorkersKey = "workers" - TxsPerWorkerKey = "txs-per-worker" - KeyDirKey = "key-dir" - VersionKey = "version" - TimeoutKey = "timeout" - BatchSizeKey = "batch-size" - BlockchainIDStrKey = "blockchain-id-str" - MetricsEndpointsKey = "metrics-endpoints" + ConfigFilePathKey = "config-file" + LogLevelKey = "log-level" + EndpointsKey = "endpoints" + MaxFeeCapKey = "max-fee-cap" + MaxTipCapKey = "max-tip-cap" + WorkersKey = "workers" + TxsPerWorkerKey = "txs-per-worker" + KeyDirKey = "key-dir" + VersionKey = "version" + TimeoutKey = "timeout" + BatchSizeKey = "batch-size" ) var ( @@ -38,30 +36,26 @@ var ( ) type Config struct { - Endpoints []string `json:"endpoints"` - MaxFeeCap int64 `json:"max-fee-cap"` - MaxTipCap int64 `json:"max-tip-cap"` - Workers int `json:"workers"` - TxsPerWorker uint64 `json:"txs-per-worker"` - KeyDir string `json:"key-dir"` - Timeout time.Duration `json:"timeout"` - BatchSize uint64 `json:"batch-size"` - BlockchainIDStr string `json:"blockchain-id-str"` - MetricsEndpoints []string `json:"metrics-endpoints"` + Endpoints []string `json:"endpoints"` + MaxFeeCap int64 `json:"max-fee-cap"` + MaxTipCap int64 `json:"max-tip-cap"` + Workers int `json:"workers"` + TxsPerWorker uint64 `json:"txs-per-worker"` + KeyDir string `json:"key-dir"` + Timeout time.Duration `json:"timeout"` + BatchSize uint64 `json:"batch-size"` } func BuildConfig(v *viper.Viper) (Config, error) { c := Config{ - Endpoints: v.GetStringSlice(EndpointsKey), - MaxFeeCap: v.GetInt64(MaxFeeCapKey), - MaxTipCap: v.GetInt64(MaxTipCapKey), - Workers: v.GetInt(WorkersKey), - TxsPerWorker: v.GetUint64(TxsPerWorkerKey), - KeyDir: v.GetString(KeyDirKey), - Timeout: v.GetDuration(TimeoutKey), - BatchSize: v.GetUint64(BatchSizeKey), - BlockchainIDStr: v.GetString(BlockchainIDStrKey), - MetricsEndpoints: v.GetStringSlice(MetricsEndpointsKey), + Endpoints: v.GetStringSlice(EndpointsKey), + MaxFeeCap: v.GetInt64(MaxFeeCapKey), + MaxTipCap: v.GetInt64(MaxTipCapKey), + Workers: v.GetInt(WorkersKey), + TxsPerWorker: v.GetUint64(TxsPerWorkerKey), + KeyDir: v.GetString(KeyDirKey), + Timeout: v.GetDuration(TimeoutKey), + BatchSize: v.GetUint64(BatchSizeKey), } if len(c.Endpoints) == 0 { return c, ErrNoEndpoints @@ -124,6 +118,4 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") - fs.String(BlockchainIDStrKey, "C", "Specify the blockchain ID for the chain you are executing the simulation on. Ex: C, X, P, pUSPHTrvs8ASVfPjrf9xdQ6SwDFhSmCZ3EKuCUMASHky2Wvr (full 32 byte hash blockchainID)") - fs.StringSlice(MetricsEndpointsKey, []string{}, "Specify a comma separated list of metric endpoints for extra logging at the end of the simulation (minimum of 1 endpoint)") } diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index 7e3e0a1e0f..4fbb2308a1 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -10,12 +10,14 @@ import ( "math/big" "github.com/ava-labs/subnet-evm/cmd/simulator/key" + "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" "github.com/ava-labs/subnet-evm/cmd/simulator/txs" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/params" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/prometheus/client_golang/prometheus" ) // DistributeFunds ensures that each address in keys has at least [minFundsPerAddr] by sending funds @@ -109,7 +111,10 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) txFunderAgent := txs.NewIssueNAgent[txs.TimedTx](txSequence, worker, numTxs) - if err := txFunderAgent.Execute(ctx); err != nil { + reg := prometheus.NewRegistry() + m := metrics.NewMetrics(reg) + + if err := txFunderAgent.Execute(ctx, m); err != nil { return nil, err } for _, addr := range needFundsAddrs { diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 38160b7bec..f8e5c4a7e2 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -6,16 +6,13 @@ package load import ( "context" "crypto/ecdsa" - "errors" "fmt" - "io/ioutil" "math/big" "net/http" - "regexp" - "time" "github.com/ava-labs/subnet-evm/cmd/simulator/config" "github.com/ava-labs/subnet-evm/cmd/simulator/key" + "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" "github.com/ava-labs/subnet-evm/cmd/simulator/txs" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" @@ -23,6 +20,8 @@ import ( "github.com/ethereum/go-ethereum/common" ethcrypto "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" "golang.org/x/sync/errgroup" ) @@ -121,12 +120,15 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { agents = append(agents, txs.NewIssueNAgent[txs.TimedTx](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) } + reg := prometheus.NewRegistry() + m := metrics.NewMetrics(reg) + log.Info("Starting tx agents...") eg := errgroup.Group{} for _, agent := range agents { agent := agent eg.Go(func() error { - return agent.Execute(ctx) + return agent.Execute(ctx, m) }) } @@ -136,69 +138,9 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - logExtraMetrics(config.MetricsEndpoints, config.BlockchainIDStr) - return nil -} - -func logExtraMetrics(metricsEndpoints []string, blockchainIDStr string) error { - if len(metricsEndpoints) == 0 { - log.Info("failed getting metrics: metricEndpoints is empty") - return nil - } - - if blockchainIDStr == "" { - log.Info("failed getting metrics: blockchainIDStr is empty") - return nil - } - - for i := 0; i < len(metricsEndpoints); i++ { - getCallStart := time.Now() - resp, err := http.Get(metricsEndpoints[i]) - getCallDuration := time.Since(getCallStart) - - log.Info("GET Metrics API Data", "time", getCallDuration.Seconds()) - if err != nil { - log.Info("failed getting metrics", "err", err) - return nil - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - log.Info("failed reading response body of metrics", "err", err) - return nil - } - - bodyString := string(body) - buildBlockTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_build_block_sum.*", blockchainIDStr)) - if err != nil { - log.Info("No buildBlock metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) - } - log.Info("Sum of time (in ns) of a build_block", "time", buildBlockTime) - - issuedToAcceptedTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_blks_accepted_sum.*", blockchainIDStr)) - if err != nil { - log.Info("No issuedToAccepted metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) - } - log.Info("Sum of time (in ns) from issuance of a block(s) to its acceptance", "time", issuedToAcceptedTime) - - verifyTime, err := findMatchFromString(bodyString, fmt.Sprintf(".*avalanche_%s_vm_metervm_verify_sum.*", blockchainIDStr)) - if err != nil { - log.Info("No verify metrics found from metrics API for blockchainIDStr", "blockchainIDStr", blockchainIDStr, "metricsEndpoint", metricsEndpoints[i]) - } - log.Info("Sum of time (in ns) of a verify", "time", verifyTime) - } + // Start a prometheus server to expose individual tx metrics + http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) + log.Info("localhost:8082/metrics") + http.ListenAndServe(":8082", nil) return nil } - -func findMatchFromString(fullString string, regex string) (string, error) { - re := regexp.MustCompile(regex) - matches := re.FindAllStringSubmatch(fullString, -1) - if len(matches) > 0 && len(matches[len(matches)-1]) > 0 { - // This is hardcoded for the metrics API. - // We know the exact metric we want will always be the last item in the - // 2D slice which only has one item. - return matches[len(matches)-1][0], nil - } - - return "", errors.New("could not find any matches for the given string") -} diff --git a/cmd/simulator/metrics/metrics.go b/cmd/simulator/metrics/metrics.go index a238c245c3..4d7fdff4f9 100644 --- a/cmd/simulator/metrics/metrics.go +++ b/cmd/simulator/metrics/metrics.go @@ -4,16 +4,16 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -type metrics struct { +type Metrics struct { // Summary of the quantiles of Individual Confirmation Tx Times ConfirmationTxTimes prometheus.Summary // Summary of the quantiles of Individual Issuance Tx Times IssuanceTxTimes prometheus.Summary } -// NewMetrics creates and returns a metrics and registers it with a Collector -func NewMetrics(reg prometheus.Registerer) *metrics { - m := &metrics{ +// NewMetrics creates and returns a Metrics and registers it with a Collector +func NewMetrics(reg prometheus.Registerer) *Metrics { + m := &Metrics{ ConfirmationTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ Name: "confirmation_tx_times", Help: "Individual Tx Confirmation Times for a Load Test", diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 6836d3dee2..f47f05d461 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -7,13 +7,10 @@ import ( "context" "errors" "fmt" - "net/http" "time" "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" "github.com/ethereum/go-ethereum/log" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" ) // TxSequence provides an interface to return a channel of transactions. @@ -34,7 +31,7 @@ type Worker[T any] interface { // Execute the work of the given agent. type Agent[T any] interface { - Execute(ctx context.Context) error + Execute(ctx context.Context, m *metrics.Metrics) error } // issueNAgent issues and confirms a batch of N transactions at a time. @@ -54,7 +51,7 @@ func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64) A } // Execute issues txs in batches of N and waits for them to confirm -func (a issueNAgent[T]) Execute(ctx context.Context) error { +func (a issueNAgent[T]) Execute(ctx context.Context, m *metrics.Metrics) error { if a.n == 0 { return errors.New("batch size n cannot be equal to 0") } @@ -63,9 +60,6 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { confirmedCount := 0 batchI := 0 - reg := prometheus.NewRegistry() - m := metrics.NewMetrics(reg) - // Tracks the total amount of time waiting for issuing and confirming txs var ( totalIssuedTime time.Duration @@ -133,9 +127,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { log.Info("Execution complete", "totalTxs", confirmedCount, "totalTime", totalTime, "TPS", float64(confirmedCount)/totalTime, "issuanceTime", totalIssuedTime.Seconds(), "confirmedTime", totalConfirmedTime.Seconds()) - // Start a prometheus server to expose individual tx metrics - http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) - log.Error("Listen", "err", http.ListenAndServe(":8082", nil)) + return nil } batchI++ diff --git a/tests/load/load_test.go b/tests/load/load_test.go index dfb12ea93c..f562704394 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -36,23 +36,14 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { nodeURIsLen := len(nodeURIs) rpcEndpoints := make([]string, 0, nodeURIsLen) - metricsEndpoints := make([]string, 0, nodeURIsLen) for _, uri := range nodeURIs { rpcEndpoints = append(rpcEndpoints, fmt.Sprintf("%s/ext/bc/%s/rpc", uri, blockchainID)) - metricsEndpoints = append(metricsEndpoints, fmt.Sprintf("%s/ext/metrics", uri)) } commaSeparatedRPCEndpoints := strings.Join(rpcEndpoints, ",") err := os.Setenv("RPC_ENDPOINTS", commaSeparatedRPCEndpoints) gomega.Expect(err).Should(gomega.BeNil()) - commaSeparatedMetricsEndpoints := strings.Join(metricsEndpoints, ",") - err = os.Setenv("METRICS_ENDPOINTS", commaSeparatedMetricsEndpoints) - gomega.Expect(err).Should(gomega.BeNil()) - - err = os.Setenv("BLOCKCHAIN_ID", blockchainID.String()) - gomega.Expect(err).Should(gomega.BeNil()) - - log.Info("Running load simulator...", "rpcEndpoints", commaSeparatedRPCEndpoints, "metricsEndpoints", commaSeparatedMetricsEndpoints, "blockchainIDStr", blockchainID.String()) + log.Info("Running load simulator...", "rpcEndpoints", commaSeparatedRPCEndpoints) cmd := exec.Command("./scripts/run_simulator.sh") log.Info("Running load simulator script", "cmd", cmd.String()) From f7d3850ce75429e5687b4ee2b887f51571b35a5b Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 11:25:39 -0700 Subject: [PATCH 40/63] cleanup --- cmd/simulator/load/loader.go | 1 - cmd/simulator/txs/tx_generator.go | 25 +++++++++---------------- go.mod | 1 - go.sum | 2 -- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index f8e5c4a7e2..259a3b74df 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -35,7 +35,6 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // Construct the arguments for the load simulator clients := make([]ethclient.Client, 0, len(config.Endpoints)) - for i := 0; i < config.Workers; i++ { clientURI := config.Endpoints[i%len(config.Endpoints)] client, err := ethclient.Dial(clientURI) diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index 6bb1755b8e..53c8afa36b 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -7,23 +7,16 @@ import ( "context" "crypto/ecdsa" "fmt" - "time" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" ethcrypto "github.com/ethereum/go-ethereum/crypto" ) -var _ TxSequence[TimedTx] = (*txSequence)(nil) +var _ TxSequence[*types.Transaction] = (*txSequence)(nil) type CreateTx func(key *ecdsa.PrivateKey, nonce uint64) (*types.Transaction, error) -type TimedTx struct { - Tx *types.Transaction - IssuanceDuration time.Duration - ConfirmationDuration time.Duration -} - // GenerateTxSequence fetches the current nonce of key and calls [generator] [numTxs] times sequentially to generate a sequence of transactions. func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclient.Client, key *ecdsa.PrivateKey, numTxs uint64) (TxSequence[TimedTx], error) { address := ethcrypto.PubkeyToAddress(key.PublicKey) @@ -31,20 +24,20 @@ func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclien if err != nil { return nil, fmt.Errorf("failed to fetch nonce for address %s: %w", address, err) } - txs := make([]TimedTx, 0, numTxs) + txs := make([]*types.Transaction, 0, numTxs) for i := uint64(0); i < numTxs; i++ { tx, err := generator(key, startingNonce+i) if err != nil { return nil, fmt.Errorf("failed to sign tx at index %d: %w", i, err) } - timedTx := TimedTx{Tx: tx} - txs = append(txs, timedTx) + + txs = append(txs, tx) } return ConvertTxSliceToSequence(txs), nil } func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[TimedTx], error) { - txSequences := make([]TxSequence[TimedTx], len(keys)) + txSequences := make([]TxSequence[*types.Transaction], len(keys)) for i, key := range keys { txs, err := GenerateTxSequence(ctx, generator, client, key, txsPerKey) if err != nil { @@ -56,11 +49,11 @@ func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclie } type txSequence struct { - txChan chan TimedTx + txChan chan *types.Transaction } -func ConvertTxSliceToSequence(txs []TimedTx) TxSequence[TimedTx] { - txChan := make(chan TimedTx, len(txs)) +func ConvertTxSliceToSequence(txs []*types.Transaction) TxSequence[*types.Transaction] { + txChan := make(chan *types.Transaction, len(txs)) for _, tx := range txs { txChan <- tx } @@ -71,6 +64,6 @@ func ConvertTxSliceToSequence(txs []TimedTx) TxSequence[TimedTx] { } } -func (t *txSequence) Chan() <-chan TimedTx { +func (t *txSequence) Chan() <-chan *types.Transaction { return t.txChan } diff --git a/go.mod b/go.mod index aadb152c27..b3bbb63dc7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/VictoriaMetrics/fastcache v1.10.0 github.com/ava-labs/avalanche-network-runner v1.6.0 github.com/ava-labs/avalanchego v1.10.2 - github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e github.com/cespare/cp v0.1.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 diff --git a/go.sum b/go.sum index 71e7953eca..ef10eee19e 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,6 @@ github.com/ava-labs/avalanchego v1.10.2 h1:kDM2xfQDaewueUCxJUujPlbNQ91gtJfXY9Z0C github.com/ava-labs/avalanchego v1.10.2/go.mod h1:PsNLfOc9FnsnoJ8CjauclvFy6BCSVZmT05I4c9rm4a4= github.com/ava-labs/coreth v0.12.2-rc.0 h1:nGhGN4bYqid5EgqH/GFky2ybY8bGRxto6Bo7nes1V+Y= github.com/ava-labs/coreth v0.12.2-rc.0/go.mod h1:/5x54QlIKjlPebkdzTA5ic9wXdejbWOnQosztkv9jxo= -github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e h1:dSeuFcs4WAJJnswS8vXy7YY1+fdlbVPuEVmDAfqvFOQ= -github.com/aybabtme/uniplot v0.0.0-20151203143629-039c559e5e7e/go.mod h1:uh71c5Vc3VNIplXOFXsnDy21T1BepgT32c5X/YPrOyc= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= From c81454eb3e8d9892a8bc529d1e163c2e267baf96 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 11:29:54 -0700 Subject: [PATCH 41/63] more cleanup --- cmd/simulator/load/funder.go | 2 +- cmd/simulator/load/loader.go | 2 +- cmd/simulator/load/worker.go | 8 +++----- cmd/simulator/txs/tx_generator.go | 4 ++-- scripts/run_simulator.sh | 4 +--- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index 4fbb2308a1..bd5015bbbc 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -109,7 +109,7 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K return nil, fmt.Errorf("failed to generate fund distribution sequence from %s of length %d", maxFundsKey.Address, len(needFundsAddrs)) } worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) - txFunderAgent := txs.NewIssueNAgent[txs.TimedTx](txSequence, worker, numTxs) + txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs) reg := prometheus.NewRegistry() m := metrics.NewMetrics(reg) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 259a3b74df..f54ce4c99a 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -116,7 +116,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { log.Info("Constructing tx agents...", "numAgents", config.Workers) agents := make([]txs.Agent[*types.Transaction], 0, config.Workers) for i := 0; i < config.Workers; i++ { - agents = append(agents, txs.NewIssueNAgent[txs.TimedTx](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) + agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) } reg := prometheus.NewRegistry() diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index 911645f013..9d3063354e 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -8,7 +8,6 @@ import ( "fmt" "time" - "github.com/ava-labs/subnet-evm/cmd/simulator/txs" "github.com/ava-labs/subnet-evm/core/types" "github.com/ava-labs/subnet-evm/ethclient" "github.com/ava-labs/subnet-evm/interfaces" @@ -45,8 +44,8 @@ func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, addr return tw } -func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timedTx txs.TimedTx) error { - err := tw.client.SendTransaction(ctx, timedTx.Tx) +func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, tx *types.Transaction) error { + err := tw.client.SendTransaction(ctx, tx) if err != nil { return err } @@ -54,8 +53,7 @@ func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, timedTx txs.TimedT return nil } -func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, timedTx txs.TimedTx) error { - tx := timedTx.Tx +func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, tx *types.Transaction) error { txNonce := tx.Nonce() for { diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index 53c8afa36b..d2c98ba151 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -18,7 +18,7 @@ var _ TxSequence[*types.Transaction] = (*txSequence)(nil) type CreateTx func(key *ecdsa.PrivateKey, nonce uint64) (*types.Transaction, error) // GenerateTxSequence fetches the current nonce of key and calls [generator] [numTxs] times sequentially to generate a sequence of transactions. -func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclient.Client, key *ecdsa.PrivateKey, numTxs uint64) (TxSequence[TimedTx], error) { +func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclient.Client, key *ecdsa.PrivateKey, numTxs uint64) (TxSequence[*types.Transaction], error) { address := ethcrypto.PubkeyToAddress(key.PublicKey) startingNonce, err := client.NonceAt(ctx, address, nil) if err != nil { @@ -36,7 +36,7 @@ func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclien return ConvertTxSliceToSequence(txs), nil } -func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[TimedTx], error) { +func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[*types.Transaction], error) { txSequences := make([]TxSequence[*types.Transaction], len(keys)) for i, key := range keys { txs, err := GenerateTxSequence(ctx, generator, client, key, txsPerKey) diff --git a/scripts/run_simulator.sh b/scripts/run_simulator.sh index 7d24d63d5b..d1fb6c4c41 100755 --- a/scripts/run_simulator.sh +++ b/scripts/run_simulator.sh @@ -36,9 +36,7 @@ run_simulator() { --timeout=30s \ --workers=1 \ --max-fee-cap=300 \ - --max-tip-cap=100 \ - --blockchain-id-str=$BLOCKCHAIN_ID \ - --metrics-endpoints=$METRICS_ENDPOINTS + --max-tip-cap=100 } run_simulator From 2fb7c3b8b748582d3fb0e7b6b1299f57cfdc7750 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 11:54:48 -0700 Subject: [PATCH 42/63] rename vars for clarity --- cmd/simulator/txs/agent.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index f47f05d461..7b3f67bfc6 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -91,12 +91,12 @@ func (a issueNAgent[T]) Execute(ctx context.Context, m *metrics.Metrics) error { if !moreTxs { break L } - start := time.Now() + issuanceIndividualStart := time.Now() if err := a.worker.IssueTx(ctx, tx); err != nil { return fmt.Errorf("failed to issue transaction %d: %w", len(txs), err) } - issuanceTime := time.Since(start) - m.IssuanceTxTimes.Observe(issuanceTime.Seconds()) + issuanceIndividualTime := time.Since(issuanceIndividualStart) + m.IssuanceTxTimes.Observe(issuanceIndividualTime.Seconds()) txs = append(txs, tx) } } @@ -108,12 +108,12 @@ func (a issueNAgent[T]) Execute(ctx context.Context, m *metrics.Metrics) error { // Wait for txs in this batch to confirm confirmedStart := time.Now() for i, tx := range txs { - start := time.Now() + confirmedIndividualStart := time.Now() if err := a.worker.ConfirmTx(ctx, tx); err != nil { return fmt.Errorf("failed to await transaction %d: %w", i, err) } - confirmationTime := time.Since(start) - m.ConfirmationTxTimes.Observe(confirmationTime.Seconds()) + confirmationIndividualTime := time.Since(confirmedIndividualStart) + m.ConfirmationTxTimes.Observe(confirmationIndividualTime.Seconds()) confirmedCount++ } // Get the batch's confirmation time and add it to totalConfirmedTime From 1773e1347808672d00e35a6a4161a4da959871ed Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 11:55:32 -0700 Subject: [PATCH 43/63] ws --- cmd/simulator/txs/tx_generator.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index d2c98ba151..85b5e2fe59 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -30,7 +30,6 @@ func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclien if err != nil { return nil, fmt.Errorf("failed to sign tx at index %d: %w", i, err) } - txs = append(txs, tx) } return ConvertTxSliceToSequence(txs), nil From f3867e5d4ea41d259e5d54c246d1146368659b12 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 11:57:40 -0700 Subject: [PATCH 44/63] cleanup --- cmd/simulator/load/worker.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index 9d3063354e..adebc21922 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -45,18 +45,14 @@ func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, addr } func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, tx *types.Transaction) error { - err := tw.client.SendTransaction(ctx, tx) - if err != nil { - return err - } - - return nil + return tw.client.SendTransaction(ctx, tx) } func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, tx *types.Transaction) error { txNonce := tx.Nonce() for { + // If the is less than what has already been accepted, the transaction is confirmed if txNonce < tw.acceptedNonce { return nil } From 3c4f54a76bf22afbbea643b36a0359ab990c1be1 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 12:26:34 -0700 Subject: [PATCH 45/63] address comments --- cmd/simulator/load/funder.go | 10 +++------- cmd/simulator/load/loader.go | 14 ++++++++------ cmd/simulator/metrics/metrics.go | 7 +++++-- cmd/simulator/txs/agent.go | 9 ++++++--- tests/load/load_test.go | 3 +-- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index bd5015bbbc..4e7cca00cc 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -17,13 +17,12 @@ import ( "github.com/ava-labs/subnet-evm/params" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" - "github.com/prometheus/client_golang/prometheus" ) // DistributeFunds ensures that each address in keys has at least [minFundsPerAddr] by sending funds // from the key with the highest starting balance. // This function returns a set of at least [numKeys] keys, each having a minimum balance [minFundsPerAddr]. -func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int) ([]*key.Key, error) { +func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int, m *metrics.Metrics) ([]*key.Key, error) { if len(keys) < numKeys { return nil, fmt.Errorf("insufficient number of keys %d < %d", len(keys), numKeys) } @@ -109,12 +108,9 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K return nil, fmt.Errorf("failed to generate fund distribution sequence from %s of length %d", maxFundsKey.Address, len(needFundsAddrs)) } worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address) - txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs) + txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs, m) - reg := prometheus.NewRegistry() - m := metrics.NewMetrics(reg) - - if err := txFunderAgent.Execute(ctx, m); err != nil { + if err := txFunderAgent.Execute(ctx); err != nil { return nil, err } for _, addr := range needFundsAddrs { diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index f54ce4c99a..d6c8f93d7c 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -66,8 +66,13 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // to fund gas for all of their transactions. maxFeeCap := new(big.Int).Mul(big.NewInt(params.GWei), big.NewInt(config.MaxFeeCap)) minFundsPerAddr := new(big.Int).Mul(maxFeeCap, big.NewInt(int64(config.TxsPerWorker*params.TxGas))) + + // Create metrics + reg := prometheus.NewRegistry() + m := metrics.NewMetrics(reg) + log.Info("Distributing funds", "numTxsPerWorker", config.TxsPerWorker, "minFunds", minFundsPerAddr) - keys, err = DistributeFunds(ctx, clients[0], keys, config.Workers, minFundsPerAddr) + keys, err = DistributeFunds(ctx, clients[0], keys, config.Workers, minFundsPerAddr, m) if err != nil { return err } @@ -116,18 +121,15 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { log.Info("Constructing tx agents...", "numAgents", config.Workers) agents := make([]txs.Agent[*types.Transaction], 0, config.Workers) for i := 0; i < config.Workers; i++ { - agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize)) + agents = append(agents, txs.NewIssueNAgent[*types.Transaction](txSequences[i], NewSingleAddressTxWorker(ctx, clients[i], senders[i]), config.BatchSize, m)) } - reg := prometheus.NewRegistry() - m := metrics.NewMetrics(reg) - log.Info("Starting tx agents...") eg := errgroup.Group{} for _, agent := range agents { agent := agent eg.Go(func() error { - return agent.Execute(ctx, m) + return agent.Execute(ctx) }) } diff --git a/cmd/simulator/metrics/metrics.go b/cmd/simulator/metrics/metrics.go index 4d7fdff4f9..376b49050b 100644 --- a/cmd/simulator/metrics/metrics.go +++ b/cmd/simulator/metrics/metrics.go @@ -1,3 +1,6 @@ +// (c) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + package metrics import ( @@ -15,12 +18,12 @@ type Metrics struct { func NewMetrics(reg prometheus.Registerer) *Metrics { m := &Metrics{ ConfirmationTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "confirmation_tx_times", + Name: "tx_confirmation_time", Help: "Individual Tx Confirmation Times for a Load Test", Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }), IssuanceTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "issuance_tx_times", + Name: "tx_issuance_time", Help: "Individual Tx Issuance Times for a Load Test", Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }), diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 7b3f67bfc6..897307c38d 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -31,7 +31,7 @@ type Worker[T any] interface { // Execute the work of the given agent. type Agent[T any] interface { - Execute(ctx context.Context, m *metrics.Metrics) error + Execute(ctx context.Context) error } // issueNAgent issues and confirms a batch of N transactions at a time. @@ -39,19 +39,21 @@ type issueNAgent[T any] struct { sequence TxSequence[T] worker Worker[T] n uint64 + metrics *metrics.Metrics } // NewIssueNAgent creates a new issueNAgent -func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64) Agent[T] { +func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64, metrics *metrics.Metrics) Agent[T] { return &issueNAgent[T]{ sequence: sequence, worker: worker, n: n, + metrics: metrics, } } // Execute issues txs in batches of N and waits for them to confirm -func (a issueNAgent[T]) Execute(ctx context.Context, m *metrics.Metrics) error { +func (a issueNAgent[T]) Execute(ctx context.Context) error { if a.n == 0 { return errors.New("batch size n cannot be equal to 0") } @@ -59,6 +61,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context, m *metrics.Metrics) error { txChan := a.sequence.Chan() confirmedCount := 0 batchI := 0 + m := a.metrics // Tracks the total amount of time waiting for issuing and confirming txs var ( diff --git a/tests/load/load_test.go b/tests/load/load_test.go index f562704394..6a8b375e9e 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -33,9 +33,8 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { blockchainID := subnetDetails.BlockchainID nodeURIs := subnetDetails.ValidatorURIs - nodeURIsLen := len(nodeURIs) - rpcEndpoints := make([]string, 0, nodeURIsLen) + rpcEndpoints := make([]string, 0, len(nodeURIs)) for _, uri := range nodeURIs { rpcEndpoints = append(rpcEndpoints, fmt.Sprintf("%s/ext/bc/%s/rpc", uri, blockchainID)) } From 14e1d55ec443f6287cefc965beb4b2ff71e0eaba Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 12:34:33 -0700 Subject: [PATCH 46/63] ws --- tests/load/load_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/load/load_test.go b/tests/load/load_test.go index 6a8b375e9e..eafe8b69a3 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -33,7 +33,6 @@ var _ = ginkgo.Describe("[Load Simulator]", ginkgo.Ordered, func() { blockchainID := subnetDetails.BlockchainID nodeURIs := subnetDetails.ValidatorURIs - rpcEndpoints := make([]string, 0, len(nodeURIs)) for _, uri := range nodeURIs { rpcEndpoints = append(rpcEndpoints, fmt.Sprintf("%s/ext/bc/%s/rpc", uri, blockchainID)) From ee390f5f07f380485f79662a2d4c62233c8a87b4 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 19 Jul 2023 14:18:24 -0700 Subject: [PATCH 47/63] expose metrics add flag --- cmd/simulator/config/flags.go | 36 +++++++++++++++++++---------------- cmd/simulator/load/loader.go | 10 ++++++---- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index 4931ee1a1f..f7a1bfbcfd 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -27,6 +27,7 @@ const ( VersionKey = "version" TimeoutKey = "timeout" BatchSizeKey = "batch-size" + ExposeMetricsKey = "expose-metrics" ) var ( @@ -36,26 +37,28 @@ var ( ) type Config struct { - Endpoints []string `json:"endpoints"` - MaxFeeCap int64 `json:"max-fee-cap"` - MaxTipCap int64 `json:"max-tip-cap"` - Workers int `json:"workers"` - TxsPerWorker uint64 `json:"txs-per-worker"` - KeyDir string `json:"key-dir"` - Timeout time.Duration `json:"timeout"` - BatchSize uint64 `json:"batch-size"` + Endpoints []string `json:"endpoints"` + MaxFeeCap int64 `json:"max-fee-cap"` + MaxTipCap int64 `json:"max-tip-cap"` + Workers int `json:"workers"` + TxsPerWorker uint64 `json:"txs-per-worker"` + KeyDir string `json:"key-dir"` + Timeout time.Duration `json:"timeout"` + BatchSize uint64 `json:"batch-size"` + ExposeMetrics bool `json:"expose-metrics"` } func BuildConfig(v *viper.Viper) (Config, error) { c := Config{ - Endpoints: v.GetStringSlice(EndpointsKey), - MaxFeeCap: v.GetInt64(MaxFeeCapKey), - MaxTipCap: v.GetInt64(MaxTipCapKey), - Workers: v.GetInt(WorkersKey), - TxsPerWorker: v.GetUint64(TxsPerWorkerKey), - KeyDir: v.GetString(KeyDirKey), - Timeout: v.GetDuration(TimeoutKey), - BatchSize: v.GetUint64(BatchSizeKey), + Endpoints: v.GetStringSlice(EndpointsKey), + MaxFeeCap: v.GetInt64(MaxFeeCapKey), + MaxTipCap: v.GetInt64(MaxTipCapKey), + Workers: v.GetInt(WorkersKey), + TxsPerWorker: v.GetUint64(TxsPerWorkerKey), + KeyDir: v.GetString(KeyDirKey), + Timeout: v.GetDuration(TimeoutKey), + BatchSize: v.GetUint64(BatchSizeKey), + ExposeMetrics: v.GetBool(ExposeMetricsKey), } if len(c.Endpoints) == 0 { return c, ErrNoEndpoints @@ -118,4 +121,5 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") + fs.Bool(ExposeMetricsKey, false, "Specify if we want to expose the metrics from the load test to a prometheus server") } diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index d6c8f93d7c..71794e0a41 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -139,9 +139,11 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - // Start a prometheus server to expose individual tx metrics - http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) - log.Info("localhost:8082/metrics") - http.ListenAndServe(":8082", nil) + if config.ExposeMetrics { + // Start a prometheus server to expose individual tx metrics + http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) + log.Info("localhost:8082/metrics") + http.ListenAndServe(":8082", nil) + } return nil } From 2825310c7259b5beb29bfbfbd8c3237082f3b54b Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 20 Jul 2023 13:29:35 -0700 Subject: [PATCH 48/63] fix blocking issue of http server and gracefully stop it --- cmd/simulator/load/loader.go | 40 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 71794e0a41..aae178a4db 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -6,9 +6,13 @@ package load import ( "context" "crypto/ecdsa" + "errors" "fmt" "math/big" "net/http" + "os" + "os/signal" + "syscall" "github.com/ava-labs/subnet-evm/cmd/simulator/config" "github.com/ava-labs/subnet-evm/cmd/simulator/key" @@ -25,6 +29,10 @@ import ( "golang.org/x/sync/errgroup" ) +const ( + MetricsPort = ":8082" // Port for the Prometheus Metrics Server +) + // ExecuteLoader creates txSequences from [config] and has txAgents execute the specified simulation. func ExecuteLoader(ctx context.Context, config config.Config) error { if config.Timeout > 0 { @@ -133,17 +141,37 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { }) } + go func(ctx context.Context) { + // Start a prometheus server to expose individual tx metrics + server := &http.Server{ + Addr: MetricsPort, + } + + go func() { + defer func() { + if err := server.Shutdown(ctx); err != nil { + log.Error("Metrics server error: %v", err) + } + log.Info("Received a SIGINT signal: Gracefully shutting down metrics server") + }() + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT) + <-sigChan + }() + + http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) + log.Info("Metrics Server: localhost:8082/metrics") + if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + log.Error("Metrics server error: %v", err) + } + + }(ctx) + log.Info("Waiting for tx agents...") if err := eg.Wait(); err != nil { return err } log.Info("Tx agents completed successfully.") - if config.ExposeMetrics { - // Start a prometheus server to expose individual tx metrics - http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) - log.Info("localhost:8082/metrics") - http.ListenAndServe(":8082", nil) - } return nil } From 85cc2f8a330092347300d4fa6f98f56271e41d5d Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 20 Jul 2023 13:33:14 -0700 Subject: [PATCH 49/63] cleanup --- cmd/simulator/config/flags.go | 36 ++++++++++++++++------------------- cmd/simulator/load/loader.go | 1 - 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index f7a1bfbcfd..4931ee1a1f 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -27,7 +27,6 @@ const ( VersionKey = "version" TimeoutKey = "timeout" BatchSizeKey = "batch-size" - ExposeMetricsKey = "expose-metrics" ) var ( @@ -37,28 +36,26 @@ var ( ) type Config struct { - Endpoints []string `json:"endpoints"` - MaxFeeCap int64 `json:"max-fee-cap"` - MaxTipCap int64 `json:"max-tip-cap"` - Workers int `json:"workers"` - TxsPerWorker uint64 `json:"txs-per-worker"` - KeyDir string `json:"key-dir"` - Timeout time.Duration `json:"timeout"` - BatchSize uint64 `json:"batch-size"` - ExposeMetrics bool `json:"expose-metrics"` + Endpoints []string `json:"endpoints"` + MaxFeeCap int64 `json:"max-fee-cap"` + MaxTipCap int64 `json:"max-tip-cap"` + Workers int `json:"workers"` + TxsPerWorker uint64 `json:"txs-per-worker"` + KeyDir string `json:"key-dir"` + Timeout time.Duration `json:"timeout"` + BatchSize uint64 `json:"batch-size"` } func BuildConfig(v *viper.Viper) (Config, error) { c := Config{ - Endpoints: v.GetStringSlice(EndpointsKey), - MaxFeeCap: v.GetInt64(MaxFeeCapKey), - MaxTipCap: v.GetInt64(MaxTipCapKey), - Workers: v.GetInt(WorkersKey), - TxsPerWorker: v.GetUint64(TxsPerWorkerKey), - KeyDir: v.GetString(KeyDirKey), - Timeout: v.GetDuration(TimeoutKey), - BatchSize: v.GetUint64(BatchSizeKey), - ExposeMetrics: v.GetBool(ExposeMetricsKey), + Endpoints: v.GetStringSlice(EndpointsKey), + MaxFeeCap: v.GetInt64(MaxFeeCapKey), + MaxTipCap: v.GetInt64(MaxTipCapKey), + Workers: v.GetInt(WorkersKey), + TxsPerWorker: v.GetUint64(TxsPerWorkerKey), + KeyDir: v.GetString(KeyDirKey), + Timeout: v.GetDuration(TimeoutKey), + BatchSize: v.GetUint64(BatchSizeKey), } if len(c.Endpoints) == 0 { return c, ErrNoEndpoints @@ -121,5 +118,4 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") - fs.Bool(ExposeMetricsKey, false, "Specify if we want to expose the metrics from the load test to a prometheus server") } diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index aae178a4db..58a8b359a6 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -164,7 +164,6 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { log.Error("Metrics server error: %v", err) } - }(ctx) log.Info("Waiting for tx agents...") From ea1e609a603b8eb2d157a7d8e4441dd20604d435 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 20 Jul 2023 13:36:44 -0700 Subject: [PATCH 50/63] use constant --- cmd/simulator/load/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 58a8b359a6..9f6e6b2e8d 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -160,7 +160,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { }() http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) - log.Info("Metrics Server: localhost:8082/metrics") + log.Info(fmt.Sprintf("Metrics Server: localhost%s/metrics", MetricsPort)) if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { log.Error("Metrics server error: %v", err) } From 2651d769f6aca6e33047c77edf1dd69864e11180 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 20 Jul 2023 15:24:55 -0700 Subject: [PATCH 51/63] add issuance to confirmation metrics --- cmd/simulator/metrics/metrics.go | 20 ++++++++++++++------ cmd/simulator/txs/agent.go | 28 +++++++++++++++++++--------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/cmd/simulator/metrics/metrics.go b/cmd/simulator/metrics/metrics.go index 376b49050b..8462e2f2e3 100644 --- a/cmd/simulator/metrics/metrics.go +++ b/cmd/simulator/metrics/metrics.go @@ -8,27 +8,35 @@ import ( ) type Metrics struct { - // Summary of the quantiles of Individual Confirmation Tx Times - ConfirmationTxTimes prometheus.Summary // Summary of the quantiles of Individual Issuance Tx Times IssuanceTxTimes prometheus.Summary + // Summary of the quantiles of Individual Confirmation Tx Times + ConfirmationTxTimes prometheus.Summary + // Summary of the quantiles of Individual Issuance To Confirmation Tx Times + IssuanceToConfirmationTxTimes prometheus.Summary } // NewMetrics creates and returns a Metrics and registers it with a Collector func NewMetrics(reg prometheus.Registerer) *Metrics { m := &Metrics{ + IssuanceTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ + Name: "tx_issuance_time", + Help: "Individual Tx Issuance Times for a Load Test", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, + }), ConfirmationTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ Name: "tx_confirmation_time", Help: "Individual Tx Confirmation Times for a Load Test", Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }), - IssuanceTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "tx_issuance_time", - Help: "Individual Tx Issuance Times for a Load Test", + IssuanceToConfirmationTxTimes: prometheus.NewSummary(prometheus.SummaryOpts{ + Name: "tx_issuance_to_confirmation_time", + Help: "Individual Tx Issuance To Confirmation Times for a Load Test", Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, }), } - reg.MustRegister(m.ConfirmationTxTimes) reg.MustRegister(m.IssuanceTxTimes) + reg.MustRegister(m.ConfirmationTxTimes) + reg.MustRegister(m.IssuanceToConfirmationTxTimes) return m } diff --git a/cmd/simulator/txs/agent.go b/cmd/simulator/txs/agent.go index 897307c38d..09c3027f07 100644 --- a/cmd/simulator/txs/agent.go +++ b/cmd/simulator/txs/agent.go @@ -10,32 +10,37 @@ import ( "time" "github.com/ava-labs/subnet-evm/cmd/simulator/metrics" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) +type THash interface { + Hash() common.Hash +} + // TxSequence provides an interface to return a channel of transactions. // The sequence is responsible for closing the channel when there are no further // transactions. -type TxSequence[T any] interface { +type TxSequence[T THash] interface { Chan() <-chan T } // Worker defines the interface for issuance and confirmation of transactions. // The caller is responsible for calling Close to cleanup resources used by the // worker at the end of the simulation. -type Worker[T any] interface { +type Worker[T THash] interface { IssueTx(ctx context.Context, tx T) error ConfirmTx(ctx context.Context, tx T) error Close(ctx context.Context) error } // Execute the work of the given agent. -type Agent[T any] interface { +type Agent[T THash] interface { Execute(ctx context.Context) error } // issueNAgent issues and confirms a batch of N transactions at a time. -type issueNAgent[T any] struct { +type issueNAgent[T THash] struct { sequence TxSequence[T] worker Worker[T] n uint64 @@ -43,7 +48,7 @@ type issueNAgent[T any] struct { } // NewIssueNAgent creates a new issueNAgent -func NewIssueNAgent[T any](sequence TxSequence[T], worker Worker[T], n uint64, metrics *metrics.Metrics) Agent[T] { +func NewIssueNAgent[T THash](sequence TxSequence[T], worker Worker[T], n uint64, metrics *metrics.Metrics) Agent[T] { return &issueNAgent[T]{ sequence: sequence, worker: worker, @@ -62,6 +67,7 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { confirmedCount := 0 batchI := 0 m := a.metrics + txMap := make(map[common.Hash]time.Time) // Tracks the total amount of time waiting for issuing and confirming txs var ( @@ -95,11 +101,12 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { break L } issuanceIndividualStart := time.Now() + txMap[tx.Hash()] = issuanceIndividualStart if err := a.worker.IssueTx(ctx, tx); err != nil { return fmt.Errorf("failed to issue transaction %d: %w", len(txs), err) } - issuanceIndividualTime := time.Since(issuanceIndividualStart) - m.IssuanceTxTimes.Observe(issuanceIndividualTime.Seconds()) + issuanceIndividualDuration := time.Since(issuanceIndividualStart) + m.IssuanceTxTimes.Observe(issuanceIndividualDuration.Seconds()) txs = append(txs, tx) } } @@ -115,8 +122,11 @@ func (a issueNAgent[T]) Execute(ctx context.Context) error { if err := a.worker.ConfirmTx(ctx, tx); err != nil { return fmt.Errorf("failed to await transaction %d: %w", i, err) } - confirmationIndividualTime := time.Since(confirmedIndividualStart) - m.ConfirmationTxTimes.Observe(confirmationIndividualTime.Seconds()) + confirmationIndividualDuration := time.Since(confirmedIndividualStart) + issuanceToConfirmationIndividualDuration := time.Since(txMap[tx.Hash()]) + m.ConfirmationTxTimes.Observe(confirmationIndividualDuration.Seconds()) + m.IssuanceToConfirmationTxTimes.Observe(issuanceToConfirmationIndividualDuration.Seconds()) + delete(txMap, tx.Hash()) confirmedCount++ } // Get the batch's confirmation time and add it to totalConfirmedTime From 92bb91f0c30809239725f25bf2ed8e3e337eed4f Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 20 Jul 2023 15:27:29 -0700 Subject: [PATCH 52/63] ws --- cmd/simulator/load/loader.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 9f6e6b2e8d..6552bf6c7a 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -171,6 +171,5 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { return err } log.Info("Tx agents completed successfully.") - return nil } From c3d777b65055f3a022b32aff6bfad14f513ca509 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 26 Jul 2023 09:13:03 -0700 Subject: [PATCH 53/63] simplify metrics server --- cmd/simulator/load/loader.go | 54 ++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 6552bf6c7a..a1a1b220a0 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -141,30 +141,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { }) } - go func(ctx context.Context) { - // Start a prometheus server to expose individual tx metrics - server := &http.Server{ - Addr: MetricsPort, - } - - go func() { - defer func() { - if err := server.Shutdown(ctx); err != nil { - log.Error("Metrics server error: %v", err) - } - log.Info("Received a SIGINT signal: Gracefully shutting down metrics server") - }() - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGINT) - <-sigChan - }() - - http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) - log.Info(fmt.Sprintf("Metrics Server: localhost%s/metrics", MetricsPort)) - if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { - log.Error("Metrics server error: %v", err) - } - }(ctx) + go startMetricsServer(ctx, reg) log.Info("Waiting for tx agents...") if err := eg.Wait(); err != nil { @@ -173,3 +150,32 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { log.Info("Tx agents completed successfully.") return nil } + +func startMetricsServer(ctx context.Context, reg *prometheus.Registry) { + // Start a prometheus server to expose individual tx metrics + server := &http.Server{ + Addr: MetricsPort, + } + // Create buffered sigChan to send SIGINT notifications + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT) + + // Start up go routine to listen for SIGINT notifications to gracefully shut down server + go func() { + defer func() { + if err := server.Shutdown(ctx); err != nil { + log.Error("Metrics server error: %v", err) + } + log.Info("Received a SIGINT signal: Gracefully shutting down metrics server") + }() + // Blocks until signal is received + <-sigChan + }() + + // Start metrics server + http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) + log.Info(fmt.Sprintf("Metrics Server: localhost%s/metrics", MetricsPort)) + if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + log.Error("Metrics server error: %v", err) + } +} From d049a98d657c231c486f3ddd1df20c3203bb7751 Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Wed, 26 Jul 2023 12:05:44 -0400 Subject: [PATCH 54/63] Bump avalanchego to v1.10.5 and bump Subnet-EVM for v0.5.3 release (#757) * Bump avalanchego to v1.10.5 and bump Subnet-EVM for v0.5.3 release * bump anr version to v1.7.1 --- README.md | 5 ++-- compatibility.json | 1 + go.mod | 13 ++++---- go.sum | 40 +++++++++++++++++-------- plugin/evm/version.go | 2 +- plugin/evm/vm_test.go | 2 +- scripts/versions.sh | 4 +-- tests/utils/subnet.go | 7 +++-- warp/aggregator/aggregation_job_test.go | 1 + warp/aggregator/signature_job_test.go | 4 ++- warp/backend_test.go | 20 ++++++------- warp/handlers/signature_request_test.go | 4 +-- 12 files changed, 62 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 8481d6ee10..39f8239977 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,9 @@ The Subnet EVM runs in a separate process from the main AvalancheGo process and [v0.4.11] AvalancheGo@v1.9.10-v1.9.16 (Protocol Version: 24) [v0.4.12] AvalancheGo@v1.9.10-v1.9.16 (Protocol Version: 24) [v0.5.0] AvalancheGo@v1.10.0 (Protocol Version: 25) -[v0.5.1] AvalancheGo@v1.10.1-v1.10.3 (Protocol Version: 26) -[v0.5.2] AvalancheGo@v1.10.1-v1.10.3 (Protocol Version: 26) +[v0.5.1] AvalancheGo@v1.10.1-v1.10.4 (Protocol Version: 26) +[v0.5.2] AvalancheGo@v1.10.1-v1.10.4 (Protocol Version: 26) +[v0.5.3] AvalancheGo@v1.10.5 (Protocol Version: 27) ``` ## API diff --git a/compatibility.json b/compatibility.json index 3448a76e2c..73cf040141 100644 --- a/compatibility.json +++ b/compatibility.json @@ -1,5 +1,6 @@ { "rpcChainVMProtocolVersion": { + "v0.5.3": 27, "v0.5.2": 26, "v0.5.1": 26, "v0.5.0": 25, diff --git a/go.mod b/go.mod index 309b279332..89b49f601d 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,13 @@ go 1.19 require ( github.com/VictoriaMetrics/fastcache v1.10.0 - github.com/ava-labs/avalanche-network-runner v1.6.1-0.20230616215223-ce1c18985fc9 - github.com/ava-labs/avalanchego v1.10.3 + github.com/ava-labs/avalanche-network-runner v1.7.1 + github.com/ava-labs/avalanchego v1.10.5 github.com/cespare/cp v0.1.0 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 - github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 github.com/ethereum/go-ethereum v1.11.4 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/fsnotify/fsnotify v1.6.0 @@ -31,7 +31,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo/v2 v2.8.1 github.com/onsi/gomega v1.26.0 - github.com/prometheus/client_golang v1.15.1 + github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_model v0.3.0 github.com/shirou/gopsutil v3.21.11+incompatible github.com/spf13/cast v1.5.0 @@ -53,7 +53,7 @@ require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/ava-labs/coreth v0.12.3-rc.1 // indirect + github.com/ava-labs/coreth v0.12.4-rc.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect @@ -80,6 +80,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect @@ -110,7 +111,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/rs/cors v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 20df737595..a0ac9fd493 100644 --- a/go.sum +++ b/go.sum @@ -69,12 +69,12 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanche-network-runner v1.6.1-0.20230616215223-ce1c18985fc9 h1:47wIVeBkG3MZ2jqawj0oT/lwCT26IBJFF+zJJhKPWko= -github.com/ava-labs/avalanche-network-runner v1.6.1-0.20230616215223-ce1c18985fc9/go.mod h1:u1ce8mSmHKgOBx6ors8Y/atoFuPB0UcCf7huO6Hb07I= -github.com/ava-labs/avalanchego v1.10.3 h1:ZWXAyOaXFDKrH+E05QNT0du+9JsyBjDDrLXjkIBK1sU= -github.com/ava-labs/avalanchego v1.10.3/go.mod h1:yVERGXCHtFbdYC6KM5krZYXzJ8LhFR98bx5hIUrEGRs= -github.com/ava-labs/coreth v0.12.3-rc.1 h1:tJWdrjmqXNKApdng4EDixZIuh9bgiH2A/nPvF6P2SpI= -github.com/ava-labs/coreth v0.12.3-rc.1/go.mod h1:0s9OD4SGh46mUhDd+VrbKv/g1NJrz5QtjLSu2Y2+f+0= +github.com/ava-labs/avalanche-network-runner v1.7.1 h1:XRC2NcchESSxSlJEgb47lAkTG5eF1t2sMs8CoJKeAuE= +github.com/ava-labs/avalanche-network-runner v1.7.1/go.mod h1:q/2ws64daRXXsiq08bVA1iESRY1CNOQQQDKPeMauZrc= +github.com/ava-labs/avalanchego v1.10.5 h1:opYyroLzhJPTJw9LlSRks8ItcezerwuGAT0MkVSotBs= +github.com/ava-labs/avalanchego v1.10.5/go.mod h1:rXAX4UaE9ORIEJcMyzN6ibv4rnLwv0zUIPLmzA0MCno= +github.com/ava-labs/coreth v0.12.4-rc.4 h1:bK9He5M9TqG9Wjd4KZ5CBxkBZMm5wWVVeZFKOsvnXic= +github.com/ava-labs/coreth v0.12.4-rc.4/go.mod h1:LZ2jvvEjotqna/qZwzeiA8zO9IIpS992DyWNZGbk7CA= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -119,8 +119,11 @@ github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -175,8 +178,8 @@ github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/docker v1.6.2 h1:HlFGsy+9/xrgMmhmN+NGhCc5SHGJ7I+kHosRR1xc/aI= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 h1:kgvzE5wLsLa7XKfV85VZl40QXaMCaeFtHpPwJ8fhotY= -github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -341,6 +344,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -386,6 +391,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= @@ -573,8 +579,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= -github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -586,8 +592,8 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -694,6 +700,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -722,7 +729,7 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -788,6 +795,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -836,6 +844,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -859,6 +868,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -924,9 +934,11 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= @@ -945,6 +957,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1013,6 +1026,7 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/plugin/evm/version.go b/plugin/evm/version.go index a74f76053a..7210321299 100644 --- a/plugin/evm/version.go +++ b/plugin/evm/version.go @@ -11,7 +11,7 @@ var ( // GitCommit is set by the build script GitCommit string // Version is the version of Subnet EVM - Version string = "v0.5.2" + Version string = "v0.5.3" ) func init() { diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index b3efd72c7e..f352324cf3 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -150,7 +150,7 @@ func NewContext() *snow.Context { if err != nil { panic(err) } - ctx.WarpSigner = avalancheWarp.NewSigner(blsSecretKey, ctx.ChainID) + ctx.WarpSigner = avalancheWarp.NewSigner(blsSecretKey, ctx.NetworkID, ctx.ChainID) ctx.PublicKey = bls.PublicFromSecretKey(blsSecretKey) return ctx } diff --git a/scripts/versions.sh b/scripts/versions.sh index 248b123d3c..230b6b738c 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash # Set up the versions to be used - populate ENV variables only if they are not already populated -SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-'v0.5.2'} +SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-'v0.5.3'} # Don't export them as they're used in the context of other calls -AVALANCHE_VERSION=${AVALANCHE_VERSION:-'v1.10.3'} +AVALANCHE_VERSION=${AVALANCHE_VERSION:-'v1.10.5'} AVALANCHEGO_VERSION=${AVALANCHEGO_VERSION:-$AVALANCHE_VERSION} GINKGO_VERSION=${GINKGO_VERSION:-'v2.2.0'} diff --git a/tests/utils/subnet.go b/tests/utils/subnet.go index f1ef053707..dc9aef3236 100644 --- a/tests/utils/subnet.go +++ b/tests/utils/subnet.go @@ -72,7 +72,7 @@ func CreateNewSubnet(ctx context.Context, genesisFilePath string) string { gomega.Expect(err).Should(gomega.BeNil()) log.Info("Creating new subnet") - createSubnetTxID, err := pWallet.IssueCreateSubnetTx(owner) + createSubnetTx, err := pWallet.IssueCreateSubnetTx(owner) gomega.Expect(err).Should(gomega.BeNil()) genesis := &core.Genesis{} @@ -80,14 +80,15 @@ func CreateNewSubnet(ctx context.Context, genesisFilePath string) string { gomega.Expect(err).Should(gomega.BeNil()) log.Info("Creating new Subnet-EVM blockchain", "genesis", genesis) - createChainTxID, err := pWallet.IssueCreateChainTx( - createSubnetTxID, + createChainTx, err := pWallet.IssueCreateChainTx( + createSubnetTx.ID(), genesisBytes, evm.ID, nil, "testChain", ) gomega.Expect(err).Should(gomega.BeNil()) + createChainTxID := createChainTx.ID() // Confirm the new blockchain is ready by waiting for the readiness endpoint infoClient := info.NewClient(DefaultLocalNodeURI) diff --git a/warp/aggregator/aggregation_job_test.go b/warp/aggregator/aggregation_job_test.go index 05ac2ae0be..a184138489 100644 --- a/warp/aggregator/aggregation_job_test.go +++ b/warp/aggregator/aggregation_job_test.go @@ -44,6 +44,7 @@ func executeSignatureAggregationTest(t testing.TB, test signatureAggregationTest require.NoError(t, res.Message.Signature.Verify( context.Background(), &res.Message.UnsignedMessage, + networkID, test.job.state, pChainHeight, test.job.minValidQuorumNum, diff --git a/warp/aggregator/signature_job_test.go b/warp/aggregator/signature_job_test.go index 59bd466156..0ed52a0eeb 100644 --- a/warp/aggregator/signature_job_test.go +++ b/warp/aggregator/signature_job_test.go @@ -26,13 +26,15 @@ var ( nodeIDs []ids.NodeID blsSecretKeys []*bls.SecretKey blsPublicKeys []*bls.PublicKey + networkID uint32 = 54321 + sourceChainID = ids.GenerateTestID() unsignedMsg *avalancheWarp.UnsignedMessage blsSignatures []*bls.Signature ) func init() { var err error - unsignedMsg, err = avalancheWarp.NewUnsignedMessage(ids.GenerateTestID(), ids.GenerateTestID(), []byte{1, 2, 3}) + unsignedMsg, err = avalancheWarp.NewUnsignedMessage(networkID, sourceChainID, []byte{1, 2, 3}) if err != nil { panic(err) } diff --git a/warp/backend_test.go b/warp/backend_test.go index 4503105924..0834b97e39 100644 --- a/warp/backend_test.go +++ b/warp/backend_test.go @@ -16,9 +16,9 @@ import ( ) var ( - sourceChainID = ids.GenerateTestID() - destinationChainID = ids.GenerateTestID() - payload = []byte("test") + networkID uint32 = 54321 + sourceChainID = ids.GenerateTestID() + payload = []byte("test") ) func TestClearDB(t *testing.T) { @@ -27,7 +27,7 @@ func TestClearDB(t *testing.T) { snowCtx := snow.DefaultContextTest() sk, err := bls.NewSecretKey() require.NoError(t, err) - snowCtx.WarpSigner = avalancheWarp.NewSigner(sk, sourceChainID) + snowCtx.WarpSigner = avalancheWarp.NewSigner(sk, networkID, sourceChainID) backend := NewWarpBackend(snowCtx, db, 500) // use multiple messages to test that all messages get cleared @@ -36,7 +36,7 @@ func TestClearDB(t *testing.T) { // add all messages for _, payload := range payloads { - unsignedMsg, err := avalancheWarp.NewUnsignedMessage(sourceChainID, destinationChainID, payload) + unsignedMsg, err := avalancheWarp.NewUnsignedMessage(networkID, sourceChainID, payload) require.NoError(t, err) messageID := hashing.ComputeHash256Array(unsignedMsg.Bytes()) messageIDs = append(messageIDs, messageID) @@ -63,11 +63,11 @@ func TestAddAndGetValidMessage(t *testing.T) { snowCtx := snow.DefaultContextTest() sk, err := bls.NewSecretKey() require.NoError(t, err) - snowCtx.WarpSigner = avalancheWarp.NewSigner(sk, sourceChainID) + snowCtx.WarpSigner = avalancheWarp.NewSigner(sk, networkID, sourceChainID) backend := NewWarpBackend(snowCtx, db, 500) // Create a new unsigned message and add it to the warp backend. - unsignedMsg, err := avalancheWarp.NewUnsignedMessage(sourceChainID, destinationChainID, payload) + unsignedMsg, err := avalancheWarp.NewUnsignedMessage(networkID, sourceChainID, payload) require.NoError(t, err) err = backend.AddMessage(unsignedMsg) require.NoError(t, err) @@ -86,7 +86,7 @@ func TestAddAndGetUnknownMessage(t *testing.T) { db := memdb.New() backend := NewWarpBackend(snow.DefaultContextTest(), db, 500) - unsignedMsg, err := avalancheWarp.NewUnsignedMessage(sourceChainID, destinationChainID, payload) + unsignedMsg, err := avalancheWarp.NewUnsignedMessage(networkID, sourceChainID, payload) require.NoError(t, err) // Try getting a signature for a message that was not added. @@ -101,13 +101,13 @@ func TestZeroSizedCache(t *testing.T) { snowCtx := snow.DefaultContextTest() sk, err := bls.NewSecretKey() require.NoError(t, err) - snowCtx.WarpSigner = avalancheWarp.NewSigner(sk, sourceChainID) + snowCtx.WarpSigner = avalancheWarp.NewSigner(sk, networkID, sourceChainID) // Verify zero sized cache works normally, because the lru cache will be initialized to size 1 for any size parameter <= 0. backend := NewWarpBackend(snowCtx, db, 0) // Create a new unsigned message and add it to the warp backend. - unsignedMsg, err := avalancheWarp.NewUnsignedMessage(sourceChainID, destinationChainID, payload) + unsignedMsg, err := avalancheWarp.NewUnsignedMessage(networkID, sourceChainID, payload) require.NoError(t, err) err = backend.AddMessage(unsignedMsg) require.NoError(t, err) diff --git a/warp/handlers/signature_request_test.go b/warp/handlers/signature_request_test.go index 79ca16d855..b431f71e9e 100644 --- a/warp/handlers/signature_request_test.go +++ b/warp/handlers/signature_request_test.go @@ -25,10 +25,10 @@ func TestSignatureHandler(t *testing.T) { blsSecretKey, err := bls.NewSecretKey() require.NoError(t, err) - snowCtx.WarpSigner = avalancheWarp.NewSigner(blsSecretKey, snowCtx.ChainID) + snowCtx.WarpSigner = avalancheWarp.NewSigner(blsSecretKey, snowCtx.NetworkID, snowCtx.ChainID) warpBackend := warp.NewWarpBackend(snowCtx, database, 100) - msg, err := avalancheWarp.NewUnsignedMessage(snowCtx.ChainID, snowCtx.CChainID, []byte("test")) + msg, err := avalancheWarp.NewUnsignedMessage(snowCtx.NetworkID, snowCtx.ChainID, []byte("test")) require.NoError(t, err) messageID := msg.ID() From 0fcf0d797a285918905b504066b9768d7d9ff6eb Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 27 Jul 2023 11:50:27 -0700 Subject: [PATCH 55/63] handle control c --- cmd/simulator/load/funder.go | 8 ++++++++ cmd/simulator/load/loader.go | 22 +++++++++++++++++----- cmd/simulator/load/worker.go | 6 ++++++ cmd/simulator/txs/tx_generator.go | 6 ++++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index 4e7cca00cc..9f2da559ff 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -23,6 +23,12 @@ import ( // from the key with the highest starting balance. // This function returns a set of at least [numKeys] keys, each having a minimum balance [minFundsPerAddr]. func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int, m *metrics.Metrics) ([]*key.Key, error) { + go func() { + <-ctx.Done() + // Gracefully close the client + client.Close() + }() + if len(keys) < numKeys { return nil, fmt.Errorf("insufficient number of keys %d < %d", len(keys), numKeys) } @@ -81,6 +87,8 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K } signer := types.LatestSignerForChainID(chainID) + client.Close() + // Generate a sequence of transactions to distribute the required funds. log.Info("Generating distribution transactions...") i := 0 diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index a1a1b220a0..5b66d1d9b2 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -41,6 +41,20 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { defer cancel() } + // Create buffered sigChan to send SIGINT notifications + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT) + + // Create context with cancel + ctx, cancel := context.WithCancel(ctx) + + go func() { + // Blocks until we receive a SIGNINT notification + <-sigChan + // Cancel the context and end all processes + cancel() + }() + // Construct the arguments for the load simulator clients := make([]ethclient.Client, 0, len(config.Endpoints)) for i := 0; i < config.Workers; i++ { @@ -152,13 +166,10 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } func startMetricsServer(ctx context.Context, reg *prometheus.Registry) { - // Start a prometheus server to expose individual tx metrics + // Create a prometheus server to expose individual tx metrics server := &http.Server{ Addr: MetricsPort, } - // Create buffered sigChan to send SIGINT notifications - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGINT) // Start up go routine to listen for SIGINT notifications to gracefully shut down server go func() { @@ -168,8 +179,9 @@ func startMetricsServer(ctx context.Context, reg *prometheus.Registry) { } log.Info("Received a SIGINT signal: Gracefully shutting down metrics server") }() + // Blocks until signal is received - <-sigChan + <-ctx.Done() }() // Start metrics server diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index adebc21922..359b9d8347 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -27,6 +27,12 @@ type singleAddressTxWorker struct { // NewSingleAddressTxWorker creates and returns a singleAddressTxWorker func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, address common.Address) *singleAddressTxWorker { + go func() { + <-ctx.Done() + // Gracefully close the client + client.Close() + }() + newHeads := make(chan *types.Header) tw := &singleAddressTxWorker{ client: client, diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index 85b5e2fe59..fdbcbee2e7 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -36,6 +36,12 @@ func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclien } func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[*types.Transaction], error) { + go func() { + <-ctx.Done() + // Gracefully close the client + client.Close() + }() + txSequences := make([]TxSequence[*types.Transaction], len(keys)) for i, key := range keys { txs, err := GenerateTxSequence(ctx, generator, client, key, txsPerKey) From ebe20cd5fd5224bc11a371c67a0f373e9c1da1fa Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 27 Jul 2023 12:54:06 -0700 Subject: [PATCH 56/63] print out output --- cmd/simulator/load/loader.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 5b66d1d9b2..c2282772e0 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -8,10 +8,12 @@ import ( "crypto/ecdsa" "errors" "fmt" + "io/ioutil" "math/big" "net/http" "os" "os/signal" + "strings" "syscall" "github.com/ava-labs/subnet-evm/cmd/simulator/config" @@ -162,6 +164,8 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { return err } log.Info("Tx agents completed successfully.") + + getOutputFromMetricsServer() return nil } @@ -191,3 +195,21 @@ func startMetricsServer(ctx context.Context, reg *prometheus.Registry) { log.Error("Metrics server error: %v", err) } } + +func getOutputFromMetricsServer() { + resp, err := http.Get(fmt.Sprintf("http://localhost%s/metrics", MetricsPort)) + if err != nil { + log.Error("cannot get response from metrics servers", "err", err) + return + } + respBody, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Error("cannot read response body", "err", err) + return + } + + parts := strings.Split(string(respBody), "\n") + for _, s := range parts { + fmt.Printf(" \t\t\t%s\n", s) + } +} From 11d4295540d177b609fdaa5c4785554522df8aa5 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 27 Jul 2023 12:57:56 -0700 Subject: [PATCH 57/63] clean up --- cmd/simulator/load/funder.go | 2 -- cmd/simulator/load/loader.go | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index 9f2da559ff..e1330d55da 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -87,8 +87,6 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K } signer := types.LatestSignerForChainID(chainID) - client.Close() - // Generate a sequence of transactions to distribute the required funds. log.Info("Generating distribution transactions...") i := 0 diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index c2282772e0..f9098c0cd6 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -197,17 +197,19 @@ func startMetricsServer(ctx context.Context, reg *prometheus.Registry) { } func getOutputFromMetricsServer() { + // Get response from server resp, err := http.Get(fmt.Sprintf("http://localhost%s/metrics", MetricsPort)) if err != nil { log.Error("cannot get response from metrics servers", "err", err) return } + // Read response body respBody, err := ioutil.ReadAll(resp.Body) if err != nil { log.Error("cannot read response body", "err", err) return } - + // Print out formatted individual metrics parts := strings.Split(string(respBody), "\n") for _, s := range parts { fmt.Printf(" \t\t\t%s\n", s) From 33cbe1695a46e3e64337f6cf92c29f2c101dda82 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 27 Jul 2023 12:59:07 -0700 Subject: [PATCH 58/63] clean up --- cmd/simulator/load/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index f9098c0cd6..5af8a60c20 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -53,7 +53,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { go func() { // Blocks until we receive a SIGNINT notification <-sigChan - // Cancel the context and end all processes + // Cancel the context and end all shared processes cancel() }() From 5c80926843a80436d8641f7ee9aca2ae9c3d830a Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 27 Jul 2023 14:13:39 -0700 Subject: [PATCH 59/63] remove go routines to close client --- cmd/simulator/load/funder.go | 6 ------ cmd/simulator/load/worker.go | 6 ------ cmd/simulator/txs/tx_generator.go | 6 ------ 3 files changed, 18 deletions(-) diff --git a/cmd/simulator/load/funder.go b/cmd/simulator/load/funder.go index e1330d55da..4e7cca00cc 100644 --- a/cmd/simulator/load/funder.go +++ b/cmd/simulator/load/funder.go @@ -23,12 +23,6 @@ import ( // from the key with the highest starting balance. // This function returns a set of at least [numKeys] keys, each having a minimum balance [minFundsPerAddr]. func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.Key, numKeys int, minFundsPerAddr *big.Int, m *metrics.Metrics) ([]*key.Key, error) { - go func() { - <-ctx.Done() - // Gracefully close the client - client.Close() - }() - if len(keys) < numKeys { return nil, fmt.Errorf("insufficient number of keys %d < %d", len(keys), numKeys) } diff --git a/cmd/simulator/load/worker.go b/cmd/simulator/load/worker.go index 359b9d8347..adebc21922 100644 --- a/cmd/simulator/load/worker.go +++ b/cmd/simulator/load/worker.go @@ -27,12 +27,6 @@ type singleAddressTxWorker struct { // NewSingleAddressTxWorker creates and returns a singleAddressTxWorker func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, address common.Address) *singleAddressTxWorker { - go func() { - <-ctx.Done() - // Gracefully close the client - client.Close() - }() - newHeads := make(chan *types.Header) tw := &singleAddressTxWorker{ client: client, diff --git a/cmd/simulator/txs/tx_generator.go b/cmd/simulator/txs/tx_generator.go index fdbcbee2e7..85b5e2fe59 100644 --- a/cmd/simulator/txs/tx_generator.go +++ b/cmd/simulator/txs/tx_generator.go @@ -36,12 +36,6 @@ func GenerateTxSequence(ctx context.Context, generator CreateTx, client ethclien } func GenerateTxSequences(ctx context.Context, generator CreateTx, client ethclient.Client, keys []*ecdsa.PrivateKey, txsPerKey uint64) ([]TxSequence[*types.Transaction], error) { - go func() { - <-ctx.Done() - // Gracefully close the client - client.Close() - }() - txSequences := make([]TxSequence[*types.Transaction], len(keys)) for i, key := range keys { txs, err := GenerateTxSequence(ctx, generator, client, key, txsPerKey) From 710bed0385ccc4866da6f73c719d891a9f03aa23 Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 31 Jul 2023 08:45:57 -0700 Subject: [PATCH 60/63] address comments --- cmd/simulator/config/flags.go | 4 ++++ cmd/simulator/load/loader.go | 36 +++++++++++++++++------------------ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/cmd/simulator/config/flags.go b/cmd/simulator/config/flags.go index 4931ee1a1f..d1db9f1b68 100644 --- a/cmd/simulator/config/flags.go +++ b/cmd/simulator/config/flags.go @@ -27,6 +27,7 @@ const ( VersionKey = "version" TimeoutKey = "timeout" BatchSizeKey = "batch-size" + MetricsPortKey = "metrics-port" ) var ( @@ -44,6 +45,7 @@ type Config struct { KeyDir string `json:"key-dir"` Timeout time.Duration `json:"timeout"` BatchSize uint64 `json:"batch-size"` + MetricsPort uint64 `json:"metrics-port"` } func BuildConfig(v *viper.Viper) (Config, error) { @@ -56,6 +58,7 @@ func BuildConfig(v *viper.Viper) (Config, error) { KeyDir: v.GetString(KeyDirKey), Timeout: v.GetDuration(TimeoutKey), BatchSize: v.GetUint64(BatchSizeKey), + MetricsPort: v.GetUint64(MetricsPortKey), } if len(c.Endpoints) == 0 { return c, ErrNoEndpoints @@ -118,4 +121,5 @@ func addSimulatorFlags(fs *pflag.FlagSet) { fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") + fs.Uint64(MetricsPortKey, 8082, "Specify the port to use for the metrics server") } diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 5af8a60c20..304fb298aa 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -13,6 +13,7 @@ import ( "net/http" "os" "os/signal" + "strconv" "strings" "syscall" @@ -32,7 +33,7 @@ import ( ) const ( - MetricsPort = ":8082" // Port for the Prometheus Metrics Server + MetricsEndpoint = "/metrics" // Endpoint for the Prometheus Metrics Server ) // ExecuteLoader creates txSequences from [config] and has txAgents execute the specified simulation. @@ -43,7 +44,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { defer cancel() } - // Create buffered sigChan to send SIGINT notifications + // Create buffered sigChan to receive SIGINT notifications sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT) @@ -51,7 +52,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { ctx, cancel := context.WithCancel(ctx) go func() { - // Blocks until we receive a SIGNINT notification + // Blocks until we receive a SIGINT notification <-sigChan // Cancel the context and end all shared processes cancel() @@ -94,6 +95,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { // Create metrics reg := prometheus.NewRegistry() m := metrics.NewMetrics(reg) + metricsPort := strconv.Itoa(int(config.MetricsPort)) log.Info("Distributing funds", "numTxsPerWorker", config.TxsPerWorker, "minFunds", minFundsPerAddr) keys, err = DistributeFunds(ctx, clients[0], keys, config.Workers, minFundsPerAddr, m) @@ -157,7 +159,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { }) } - go startMetricsServer(ctx, reg) + go startMetricsServer(ctx, metricsPort, reg) log.Info("Waiting for tx agents...") if err := eg.Wait(); err != nil { @@ -165,40 +167,38 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - getOutputFromMetricsServer() + getOutputFromMetricsServer(metricsPort) return nil } -func startMetricsServer(ctx context.Context, reg *prometheus.Registry) { +func startMetricsServer(ctx context.Context, metricsPort string, reg *prometheus.Registry) { // Create a prometheus server to expose individual tx metrics server := &http.Server{ - Addr: MetricsPort, + Addr: metricsPort, } // Start up go routine to listen for SIGINT notifications to gracefully shut down server go func() { - defer func() { - if err := server.Shutdown(ctx); err != nil { - log.Error("Metrics server error: %v", err) - } - log.Info("Received a SIGINT signal: Gracefully shutting down metrics server") - }() - // Blocks until signal is received <-ctx.Done() + + if err := server.Shutdown(ctx); err != nil { + log.Error("Metrics server error: %v", err) + } + log.Info("Received a SIGINT signal: Gracefully shutting down metrics server") }() // Start metrics server - http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) - log.Info(fmt.Sprintf("Metrics Server: localhost%s/metrics", MetricsPort)) + http.Handle(MetricsEndpoint, promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) + log.Info(fmt.Sprintf("Metrics Server: localhost:%s%s", metricsPort, MetricsEndpoint)) if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { log.Error("Metrics server error: %v", err) } } -func getOutputFromMetricsServer() { +func getOutputFromMetricsServer(metricsPort string) { // Get response from server - resp, err := http.Get(fmt.Sprintf("http://localhost%s/metrics", MetricsPort)) + resp, err := http.Get(fmt.Sprintf("http://localhost:%s%s", metricsPort, MetricsEndpoint)) if err != nil { log.Error("cannot get response from metrics servers", "err", err) return From e1cf6c3f62e26accf757ed4e17b9c46f8c94e32f Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 31 Jul 2023 09:02:59 -0700 Subject: [PATCH 61/63] memory leak --- cmd/simulator/load/loader.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 304fb298aa..30c525b799 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -52,9 +52,13 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { ctx, cancel := context.WithCancel(ctx) go func() { - // Blocks until we receive a SIGINT notification - <-sigChan - // Cancel the context and end all shared processes + // Blocks until we receive a SIGINT notification or if parent context is done + select { + case <-sigChan: + case <-ctx.Done(): + } + + // Cancel the child context and end all processes cancel() }() From 8b87e94f863676ef9b87ea37539a0b0fba851342 Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 31 Jul 2023 09:44:46 -0700 Subject: [PATCH 62/63] fix --- cmd/simulator/load/loader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 30c525b799..658cbe17ab 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -178,7 +178,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { func startMetricsServer(ctx context.Context, metricsPort string, reg *prometheus.Registry) { // Create a prometheus server to expose individual tx metrics server := &http.Server{ - Addr: metricsPort, + Addr: fmt.Sprintf(":%s", metricsPort), } // Start up go routine to listen for SIGINT notifications to gracefully shut down server From a2ff6f9dff42f13d2e30bc37f436db75060dc833 Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 31 Jul 2023 09:47:28 -0700 Subject: [PATCH 63/63] print --- cmd/simulator/load/loader.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/simulator/load/loader.go b/cmd/simulator/load/loader.go index 658cbe17ab..2c8458f035 100644 --- a/cmd/simulator/load/loader.go +++ b/cmd/simulator/load/loader.go @@ -171,7 +171,7 @@ func ExecuteLoader(ctx context.Context, config config.Config) error { } log.Info("Tx agents completed successfully.") - getOutputFromMetricsServer(metricsPort) + printOutputFromMetricsServer(metricsPort) return nil } @@ -200,7 +200,7 @@ func startMetricsServer(ctx context.Context, metricsPort string, reg *prometheus } } -func getOutputFromMetricsServer(metricsPort string) { +func printOutputFromMetricsServer(metricsPort string) { // Get response from server resp, err := http.Get(fmt.Sprintf("http://localhost:%s%s", metricsPort, MetricsEndpoint)) if err != nil {