Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Adding Metrics to the node #671

Merged
merged 44 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
fae9af5
Adding OpenTelemtry Metrics
otherview Feb 26, 2024
ac4b87d
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview Feb 26, 2024
dfd4946
lint
otherview Feb 26, 2024
cc93a6f
adding a swagger for the metrics endpoint
otherview Feb 26, 2024
02a60dd
adding a swagger for the metrics endpoint
otherview Feb 26, 2024
66cb875
using prometheus instead of otel due to go version incompat
otherview Feb 26, 2024
b14196e
metrics are disabled by default
otherview Feb 27, 2024
99e5b7b
Added telemetry address flag + updated swagger
otherview Feb 27, 2024
e6cd9b9
Merge branch 'master' into pedro/add_metrics
otherview Mar 14, 2024
c0ef281
Adding gauges, histogram and counter vectors
otherview Mar 18, 2024
04ce5d1
lint
otherview Mar 18, 2024
3451110
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview Mar 25, 2024
4246fa9
clean up
otherview Mar 26, 2024
4d51cd1
code cov
otherview Mar 26, 2024
3825cdf
clean flag name + update swagger
otherview Mar 26, 2024
f500ae7
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview Apr 2, 2024
06c6e78
Extend metrics in the code base (#684)
otherview Apr 22, 2024
1f97b95
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview Apr 22, 2024
68e80f6
Update api/api.go
otherview Apr 22, 2024
7be5d11
Update cmd/thor/flags.go
otherview Apr 22, 2024
70b562d
adding readme
otherview Apr 22, 2024
c55ffef
Merge branch 'pedro/add_metrics' of github.com:vechain/thor into pedr…
otherview Apr 22, 2024
ba2f8a1
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview Apr 22, 2024
e6754b4
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview Apr 23, 2024
3f8ef41
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview Apr 26, 2024
b5fb3e8
pr comments 1
otherview Apr 26, 2024
c96b676
pr comments
otherview Apr 26, 2024
9b12759
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview May 14, 2024
a05872c
remove CORS from telemetry api
otherview May 14, 2024
be9d5d6
license
otherview May 14, 2024
dbda706
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview May 16, 2024
ebb28cb
Update p2psrv/metrics.go
otherview May 16, 2024
deb4f62
Update telemetry/prometheus.go
otherview May 16, 2024
2c0ac8e
pr comments
otherview May 16, 2024
ddf59c7
Merge branch 'pedro/add_metrics' of github.com:vechain/thor into pedr…
otherview May 17, 2024
d50a415
Rename telemetry to metrics (#743)
libotony May 20, 2024
ab333ae
flag updated to enabled-metrics
otherview May 20, 2024
0b16fb5
update readme
otherview May 21, 2024
605738d
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview May 21, 2024
abd4bcb
tweak metrics in txpool and node (#744)
libotony May 22, 2024
9c90d3d
pr comments
otherview May 22, 2024
449388b
Merge remote-tracking branch 'origin/master' into pedro/add_metrics
otherview May 22, 2024
8d87599
pr comments
otherview May 22, 2024
8ca08ff
Update cmd/thor/node/node.go
libotony May 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions api/accounts/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,23 @@ func (a *Accounts) handleBatchCallData(batchCallData *BatchCallData) (txCtx *xen
func (a *Accounts) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("/*").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(a.handleCallBatchCode))
sub.Path("/{address}").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(a.handleGetAccount))
sub.Path("/{address}/code").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(a.handleGetCode))
sub.Path("/{address}/storage/{key}").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(a.handleGetStorage))
sub.Path("").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(a.handleCallContract))
sub.Path("/{address}").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(a.handleCallContract))
sub.Path("/*").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "accounts_call_batch_code", a.handleCallBatchCode))
sub.Path("/{address}").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "accounts_get_account", a.handleGetAccount))
sub.Path("/{address}/code").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "accounts_get_code", a.handleGetCode))
sub.Path("/{address}/storage/{key}").
Methods("GET").
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "accounts_get_storage", a.handleGetStorage))
// These two methods are currently deprecated
sub.Path("").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "accounts_api_call_contract", a.handleCallContract))
sub.Path("/{address}").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "accounts_call_contract_address", a.handleCallContract))
}
2 changes: 1 addition & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func New(

router := mux.NewRouter()

// to serve api docs
// to serve stoplight, swagger and api docs
router.PathPrefix("/doc").Handler(
http.StripPrefix("/doc/", http.FileServer(http.FS(doc.FS))),
)
Expand Down
4 changes: 3 additions & 1 deletion api/blocks/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,7 @@ func (b *Blocks) isTrunk(blkID thor.Bytes32, blkNum uint32) (bool, error) {

func (b *Blocks) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()
sub.Path("/{revision}").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(b.handleGetBlock))
sub.Path("/{revision}").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "blocks_get_block", b.handleGetBlock))
}
12 changes: 9 additions & 3 deletions api/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,13 @@ func (d *Debug) handleTraceCallOption(opt *TraceCallOption) (*xenv.TransactionCo
func (d *Debug) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("/tracers").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(d.handleTraceClause))
sub.Path("/tracers/call").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(d.handleTraceCall))
sub.Path("/storage-range").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(d.handleDebugStorage))
sub.Path("/tracers").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "debug_trace_clause", d.handleTraceClause))
sub.Path("/tracers/call").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "debug_trace_call", d.handleTraceCall))
sub.Path("/storage-range").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "debug_debug_storage", d.handleDebugStorage))
}
4 changes: 3 additions & 1 deletion api/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,7 @@ func (e *Events) handleFilter(w http.ResponseWriter, req *http.Request) error {
func (e *Events) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(e.handleFilter))
sub.Path("").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "events_filter", e.handleFilter))
}
4 changes: 3 additions & 1 deletion api/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,7 @@ func (n *Node) handleNetwork(w http.ResponseWriter, req *http.Request) error {
func (n *Node) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("/network/peers").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(n.handleNetwork))
sub.Path("/network/peers").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "node_network", n.handleNetwork))
}
8 changes: 6 additions & 2 deletions api/subscriptions/subscriptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@ func (s *Subscriptions) Close() {
func (s *Subscriptions) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("/txpool").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(s.handlePendingTransactions))
sub.Path("/{subject}").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(s.handleSubject))
sub.Path("/txpool").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "subscriptions_pending_transactions", s.handlePendingTransactions))
sub.Path("/{subject}").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "subscriptions_subject", s.handleSubject))
}
12 changes: 9 additions & 3 deletions api/transactions/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,13 @@ func (t *Transactions) parseHead(head string) (thor.Bytes32, error) {
func (t *Transactions) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(t.handleSendTransaction))
sub.Path("/{id}").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(t.handleGetTransactionByID))
sub.Path("/{id}/receipt").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(t.handleGetTransactionReceiptByID))
sub.Path("").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "transactions_send_transaction", t.handleSendTransaction))
sub.Path("/{id}").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "transactions_get_transaction_by_id", t.handleGetTransactionByID))
sub.Path("/{id}/receipt").
Methods(http.MethodGet).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "transactions_get_transaction_by_receipt", t.handleGetTransactionReceiptByID))
}
4 changes: 3 additions & 1 deletion api/transfers/transfers.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,7 @@ func (t *Transfers) handleFilterTransferLogs(w http.ResponseWriter, req *http.Re
func (t *Transfers) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(t.handleFilterTransferLogs))
sub.Path("").
Methods(http.MethodPost).
HandlerFunc(utils.MetricsWrapHandlerFunc(pathPrefix, "transfers_transfer_logs", t.handleFilterTransferLogs))
}
37 changes: 37 additions & 0 deletions api/utils/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
"encoding/json"
"io"
"net/http"
"strconv"
"strings"
"time"

"github.com/vechain/thor/v2/metrics"
)

type httpError struct {
Expand Down Expand Up @@ -67,6 +72,38 @@ func WrapHandlerFunc(f HandlerFunc) http.HandlerFunc {
}
}

// MetricsWrapHandlerFunc wraps a given handler and adds metrics to it
func MetricsWrapHandlerFunc(pathPrefix, endpoint string, f HandlerFunc) http.HandlerFunc {
otherview marked this conversation as resolved.
Show resolved Hide resolved
fixedPath := strings.ReplaceAll(pathPrefix, "/", "_") // ensure no unexpected slashes
httpReqCounter := metrics.CounterVec(fixedPath+"_request_count", []string{"path", "code", "method"})
httpReqDuration := metrics.HistogramVec(
fixedPath+"_duration_ms", []string{"path", "code", "method"}, metrics.BucketHTTPReqs,
)

return func(w http.ResponseWriter, r *http.Request) {
now := time.Now()
err := f(w, r)

method := r.Method
status := http.StatusOK
if err != nil {
if he, ok := err.(*httpError); ok {
if he.cause != nil {
http.Error(w, he.cause.Error(), he.status)
} else {
w.WriteHeader(he.status)
}
status = he.status
} else {
http.Error(w, err.Error(), http.StatusInternalServerError)
status = http.StatusInternalServerError
}
}
httpReqCounter.AddWithLabel(1, map[string]string{"path": endpoint, "code": strconv.Itoa(status), "method": method})
httpReqDuration.ObserveWithLabels(time.Since(now).Milliseconds(), map[string]string{"path": endpoint, "code": strconv.Itoa(status), "method": method})
}
}

// content types
const (
JSONContentType = "application/json; charset=utf-8"
Expand Down
4 changes: 3 additions & 1 deletion bft/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"sort"
"sync/atomic"

lru "github.com/hashicorp/golang-lru"
"github.com/pkg/errors"
"github.com/vechain/thor/v2/block"
"github.com/vechain/thor/v2/builtin"
Expand All @@ -18,6 +17,8 @@ import (
"github.com/vechain/thor/v2/muxdb"
"github.com/vechain/thor/v2/state"
"github.com/vechain/thor/v2/thor"

lru "github.com/hashicorp/golang-lru"
)

const dataStoreName = "bft.engine"
Expand Down Expand Up @@ -131,6 +132,7 @@ func (engine *BFTEngine) CommitBlock(header *block.Header, isPacking bool) error
return err
}
engine.finalized.Store(id)
metricBlocksCommitted().Add(1)
}
}

Expand Down
14 changes: 14 additions & 0 deletions bft/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) 2024 The VeChainThor developers

// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying
// file LICENSE or <https://www.gnu.org/licenses/lgpl-3.0.html>

package bft

import (
"github.com/vechain/thor/v2/metrics"
)

var (
metricBlocksCommitted = metrics.LazyLoadCounter("bft_committed_count")
)
10 changes: 5 additions & 5 deletions block/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"sync/atomic"

"github.com/ethereum/go-ethereum/rlp"
"github.com/vechain/thor/v2/metric"
"github.com/vechain/thor/v2/thor"
"github.com/vechain/thor/v2/tx"
)

Expand Down Expand Up @@ -90,16 +90,16 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
header: &payload.Header,
txs: payload.Txs,
}
b.cache.size.Store(metric.StorageSize(rlp.ListSize(size)))
b.cache.size.Store(thor.StorageSize(rlp.ListSize(size)))
return nil
}

// Size returns block size in bytes.
func (b *Block) Size() metric.StorageSize {
func (b *Block) Size() thor.StorageSize {
if cached := b.cache.size.Load(); cached != nil {
return cached.(metric.StorageSize)
return cached.(thor.StorageSize)
}
var size metric.StorageSize
var size thor.StorageSize
rlp.Encode(&size, b)
b.cache.size.Store(size)
return size
Expand Down
10 changes: 10 additions & 0 deletions cmd/thor/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ var (
Name: "disable-pruner",
Usage: "disable state pruner to keep all history",
}
metricsEnabledFlag = cli.BoolFlag{
Name: "enable-metrics",
Usage: "enables metrics collection",
}
metricsAddrFlag = cli.StringFlag{
Name: "metrics-addr",
Value: "localhost:2112",
Usage: "metrics service listening address",
}

// solo mode only flags
onDemandFlag = cli.BoolFlag{
Name: "on-demand",
Expand Down
34 changes: 32 additions & 2 deletions cmd/thor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/vechain/thor/v2/cmd/thor/solo"
"github.com/vechain/thor/v2/genesis"
"github.com/vechain/thor/v2/logdb"
"github.com/vechain/thor/v2/metrics"
"github.com/vechain/thor/v2/muxdb"
"github.com/vechain/thor/v2/state"
"github.com/vechain/thor/v2/thor"
Expand Down Expand Up @@ -89,6 +90,8 @@ func main() {
pprofFlag,
verifyLogsFlag,
disablePrunerFlag,
metricsEnabledFlag,
metricsAddrFlag,
},
Action: defaultAction,
Commands: []cli.Command{
Expand Down Expand Up @@ -117,6 +120,8 @@ func main() {
txPoolLimitFlag,
txPoolLimitPerAccountFlag,
disablePrunerFlag,
metricsEnabledFlag,
metricsAddrFlag,
},
Action: soloAction,
},
Expand Down Expand Up @@ -145,6 +150,19 @@ func defaultAction(ctx *cli.Context) error {
defer func() { log.Info("exited") }()

initLogger(ctx)

// enable metrics as soon as possible
metricsURL := ""
if ctx.Bool(metricsEnabledFlag.Name) {
metrics.InitializePrometheusMetrics()
url, close, err := startMetricsServer(ctx.String(metricsAddrFlag.Name))
if err != nil {
return fmt.Errorf("unable to start metrics server - %w", err)
}
metricsURL = url
defer func() { log.Info("stopping metrics server..."); close() }()
}

gene, forkConfig, err := selectGenesis(ctx)
if err != nil {
return err
Expand Down Expand Up @@ -223,7 +241,7 @@ func defaultAction(ctx *cli.Context) error {
}
defer func() { log.Info("stopping API server..."); srvCloser() }()

printStartupMessage2(apiURL, p2pCommunicator.Enode())
printStartupMessage2(gene, apiURL, p2pCommunicator.Enode(), metricsURL)

if err := p2pCommunicator.Start(); err != nil {
return err
Expand Down Expand Up @@ -253,6 +271,18 @@ func soloAction(ctx *cli.Context) error {

initLogger(ctx)

// enable metrics as soon as possible
metricsURL := ""
if ctx.Bool(metricsEnabledFlag.Name) {
metrics.InitializePrometheusMetrics()
url, close, err := startMetricsServer(ctx.String(metricsAddrFlag.Name))
if err != nil {
return fmt.Errorf("unable to start metrics server - %w", err)
}
metricsURL = url
defer func() { log.Info("stopping metrics server..."); close() }()
}

var (
gene *genesis.Genesis
forkConfig thor.ForkConfig
Expand Down Expand Up @@ -346,7 +376,7 @@ func soloAction(ctx *cli.Context) error {
return errors.New("block-interval cannot be zero")
}

printSoloStartupMessage(gene, repo, instanceDir, apiURL, forkConfig)
printSoloStartupMessage(gene, repo, instanceDir, apiURL, forkConfig, metricsURL)

optimizer := optimizer.New(mainDB, repo, !ctx.Bool(disablePrunerFlag.Name))
defer func() { log.Info("stopping optimizer..."); optimizer.Stop() }()
Expand Down
19 changes: 19 additions & 0 deletions cmd/thor/node/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2024 The VeChainThor developers

// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying
// file LICENSE or <https://www.gnu.org/licenses/lgpl-3.0.html>

package node

import (
"github.com/vechain/thor/v2/metrics"
)

var (
metricBlockProcessedCount = metrics.LazyLoadCounterVec("block_processed_count", []string{"type", "success"})
metricBlockProcessedTxs = metrics.LazyLoadCounterVec("block_processed_tx_count", []string{"type"})
metricBlockProcessedGas = metrics.LazyLoadCounterVec("block_processed_gas_count", []string{"type"})
metricBlockProcessedDuration = metrics.LazyLoadHistogram("block_processed_duration_ms", metrics.Bucket10s)
metricChainForkCount = metrics.LazyLoadCounter("chain_fork_count")
metricChainForkSize = metrics.LazyLoadGauge("chain_fork_size")
)
Loading
Loading