Skip to content

Commit

Permalink
make eth node log level configurable via TOML
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofel committed May 7, 2024
1 parent 6c03a0c commit 14d4928
Show file tree
Hide file tree
Showing 14 changed files with 164 additions and 61 deletions.
13 changes: 13 additions & 0 deletions config/private_ethereum_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
_ "embed"
"errors"
"fmt"
"strings"
"time"

"github.com/pelletier/go-toml/v2"
Expand All @@ -17,6 +18,7 @@ import (
var (
ErrMissingEthereumVersion = errors.New("ethereum version is required")
ErrMissingExecutionLayer = errors.New("execution layer is required")
DefaultNodeLogLevel = "info"
)

type EthereumNetworkConfig struct {
Expand All @@ -31,6 +33,7 @@ type EthereumNetworkConfig struct {
ValKeysDir *string `toml:"val_keys_dir"`
EthereumChainConfig *EthereumChainConfig `toml:"EthereumChainConfig"`
CustomDockerImages map[ContainerType]string `toml:"CustomDockerImages"`
NodeLogLevel *string `toml:"node_log_level,omitempty"`
}

func (en *EthereumNetworkConfig) Validate() error {
Expand Down Expand Up @@ -74,6 +77,16 @@ func (en *EthereumNetworkConfig) Validate() error {
en.ConsensusLayer = nil
}

if en.NodeLogLevel == nil {
en.NodeLogLevel = &DefaultNodeLogLevel
}

switch strings.ToLower(*en.NodeLogLevel) {
case "trace", "debug", "info", "warn", "error":
default:
return fmt.Errorf("invalid node log level: %s", *en.NodeLogLevel)
}

if en.EthereumChainConfig == nil {
return errors.New("ethereum chain config is required")
}
Expand Down
1 change: 1 addition & 0 deletions config/tomls/default_ethereum_env.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ethereum_version="eth2"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false
node_log_level="info"

[PrivateEthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
Expand Down
2 changes: 1 addition & 1 deletion docker/test_env/besu_eth1.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (g *Besu) getEth1ContainerRequest() (*tc.ContainerRequest, error) {
"--miner-enabled=true",
"--miner-coinbase", RootFundingAddr,
fmt.Sprintf("--network-id=%d", g.chainConfig.ChainID),
"--logging=DEBUG",
fmt.Sprintf("--logging=%s", strings.ToUpper(g.LogLevel)),
},
Files: []tc.ContainerFile{
{
Expand Down
2 changes: 1 addition & 1 deletion docker/test_env/besu_eth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (g *Besu) getEth2ContainerRequest() (*tc.ContainerRequest, error) {
fmt.Sprintf("--engine-rpc-port=%s", ETH2_EXECUTION_PORT),
"--sync-mode=FULL",
"--data-storage-format=BONSAI",
// "--logging=DEBUG",
fmt.Sprintf("--logging=%s", strings.ToUpper(g.LogLevel)),
"--rpc-tx-feecap=0",
},
Env: map[string]string{
Expand Down
9 changes: 9 additions & 0 deletions docker/test_env/env_component.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type EnvComponent struct {
PostStartsHooks []tc.ContainerHook `json:"-"`
PostStopsHooks []tc.ContainerHook `json:"-"`
PreTerminatesHooks []tc.ContainerHook `json:"-"`
LogLevel string `json:"-"`
}

type EnvComponentOption = func(c *EnvComponent)
Expand All @@ -52,6 +53,14 @@ func WithContainerImageWithVersion(imageWithVersion string) EnvComponentOption {
}
}

func WithLogLevel(logLevel string) EnvComponentOption {
return func(c *EnvComponent) {
if logLevel != "" {
c.LogLevel = logLevel
}
}
}

func WithLogStream(ls *logstream.LogStream) EnvComponentOption {
return func(c *EnvComponent) {
c.LogStream = ls
Expand Down
4 changes: 3 additions & 1 deletion docker/test_env/erigon_eth1.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,18 @@ func (g *Erigon) buildPowInitScript(minerAddr string) (string, error) {
echo "Starting Erigon..."
erigon --http --http.api=eth,erigon,engine,web3,net,debug,trace,txpool,admin --http.addr=0.0.0.0 --http.corsdomain=* --http.vhosts=* --http.port={{.HttpPort}} --ws \
--allow-insecure-unlock --nodiscover --networkid={{.ChainID}} --mine --miner.etherbase={{.MinerAddr}} --fakepow`
--allow-insecure-unlock --nodiscover --networkid={{.ChainID}} --mine --miner.etherbase={{.MinerAddr}} --fakepow --verbosity={{.LogLevel}}`

data := struct {
HttpPort string
ChainID int
MinerAddr string
LogLevel string
}{
HttpPort: DEFAULT_EVM_NODE_HTTP_PORT,
ChainID: g.chainConfig.ChainID,
MinerAddr: minerAddr,
LogLevel: g.LogLevel,
}

t, err := template.New("init").Parse(initTemplate)
Expand Down
16 changes: 13 additions & 3 deletions docker/test_env/erigon_eth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func (g *Erigon) buildPosInitScript() (string, error) {
}

initTemplate := `#!/bin/bash
echo "BAM!"
echo "Copied genesis file to {{.ExecutionDir}}"
mkdir -p {{.ExecutionDir}}
cp {{.GeneratedDataDir}}/genesis.json {{.ExecutionDir}}/genesis.json
Expand All @@ -124,9 +125,14 @@ func (g *Erigon) buildPosInitScript() (string, error) {
fi
echo "Starting Erigon..."
erigon --http --http.api=eth,erigon,engine,web3,net,debug,trace,txpool,admin --http.addr=0.0.0.0 --http.corsdomain=* \
--http.vhosts=* --http.port={{.HttpPort}} --ws --authrpc.vhosts=* --authrpc.addr=0.0.0.0 --authrpc.jwtsecret={{.JwtFileLocation}} \
--datadir={{.ExecutionDir}} {{.ExtraExecutionFlags}} --allow-insecure-unlock --nodiscover --networkid={{.ChainID}}`
command="erigon --http --http.api=eth,erigon,engine,web3,net,debug,trace,txpool,admin --http.addr=0.0.0.0 --http.corsdomain=* --http.vhosts=* --http.port={{.HttpPort}} --ws --authrpc.vhosts=* --authrpc.addr=0.0.0.0 --authrpc.jwtsecret={{.JwtFileLocation}} --datadir={{.ExecutionDir}} {{.ExtraExecutionFlags}} --allow-insecure-unlock --nodiscover --networkid={{.ChainID}} --log.console.verbosity={{.LogLevel}} --verbosity={{.LogLevel}}"
if [ "{{.LogLevel}}" == "trace" ]; then
echo "Enabling trace logging for senders: {{.SendersToTrace}}"
command="$command --txpool.trace.senders=\"{{.SendersToTrace}}\""
fi
eval $command`

data := struct {
HttpPort string
Expand All @@ -135,13 +141,17 @@ func (g *Erigon) buildPosInitScript() (string, error) {
JwtFileLocation string
ExecutionDir string
ExtraExecutionFlags string
SendersToTrace string
LogLevel string
}{
HttpPort: DEFAULT_EVM_NODE_HTTP_PORT,
ChainID: g.chainConfig.ChainID,
GeneratedDataDir: GENERATED_DATA_DIR_INSIDE_CONTAINER,
JwtFileLocation: JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER,
ExecutionDir: "/home/erigon/execution-data",
ExtraExecutionFlags: extraExecutionFlags,
SendersToTrace: strings.Join(g.chainConfig.AddressesToFund, ","),
LogLevel: g.LogLevel,
}

t, err := template.New("init").Parse(initTemplate)
Expand Down
14 changes: 9 additions & 5 deletions docker/test_env/ethereum_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package test_env
import (
"fmt"
"os"
"strings"
"testing"
"time"

Expand All @@ -20,14 +21,12 @@ import (
)

const (
CONFIG_ENV_VAR_NAME = "PRIVATE_ETHEREUM_NETWORK_CONFIG_PATH"
EXEC_CLIENT_ENV_VAR_NAME = "ETH2_EL_CLIENT"
CONFIG_ENV_VAR_NAME = "PRIVATE_ETHEREUM_NETWORK_CONFIG_PATH"
)

var (
ErrMissingConsensusLayer = errors.New("consensus layer is required for PoS")
ErrConsensusLayerNotAllowed = errors.New("consensus layer is not allowed for PoW")
ErrTestConfigNotSaved = errors.New("could not save test env config")
ErrMissingConsensusLayer = errors.New("consensus layer is required for PoS")
ErrTestConfigNotSaved = errors.New("could not save test env config")
)

var MsgMismatchedExecutionClient = "you provided a custom docker image for %s execution client, but explicitly set a execution client to %s. Make them match or remove one or the other"
Expand Down Expand Up @@ -711,6 +710,11 @@ func (en *EthereumNetwork) getExecutionLayerEnvComponentOpts() []EnvComponentOpt
opts = append(opts, en.getImageOverride(config.ContainerType_ExecutionLayer)...)
opts = append(opts, en.setExistingContainerName(config.ContainerType_ExecutionLayer))
opts = append(opts, WithLogStream(en.ls))

if en.NodeLogLevel != nil && *en.NodeLogLevel != "" {
opts = append(opts, WithLogLevel(strings.ToLower(*en.NodeLogLevel)))
}

return opts
}

Expand Down
85 changes: 85 additions & 0 deletions docker/test_env/ethereum_env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,91 @@ func TestEthEnvCustomDockerImagesFromToml(t *testing.T) {
require.Contains(t, fmt.Sprintf(MsgUnsupportedDockerImage, "i-dont-exist"), err.Error(), "Error message is not correct")
}

func TestEthNoLogLevelDefaultsToInfo(t *testing.T) {
t.Parallel()
tomlStr := `
[EthereumNetwork]
consensus_type="pos"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false
[EthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
slots_per_epoch=2
genesis_delay=20
validator_count=8
chain_id=1234
addresses_to_fund=["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x742d35Cc6634C0532925a3b844Bc454e4438f44f"]
`

tomlCfg, err := readEthereumNetworkConfig(tomlStr)
require.NoError(t, err, "Couldn't read config")

tomlCfg.EthereumChainConfig.GenerateGenesisTimestamp()

err = tomlCfg.Validate()
require.NoError(t, err, "Failed to validate correct TOML config")
require.Equal(t, config.DefaultNodeLogLevel, *tomlCfg.NodeLogLevel, "Incorrect default log level")
}

func TestEthLogLevelTrace(t *testing.T) {
t.Parallel()
tomlStr := `
[EthereumNetwork]
consensus_type="pos"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false
node_log_level="trace"
[EthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
slots_per_epoch=2
genesis_delay=20
validator_count=8
chain_id=1234
addresses_to_fund=["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x742d35Cc6634C0532925a3b844Bc454e4438f44f"]
`

tomlCfg, err := readEthereumNetworkConfig(tomlStr)
require.NoError(t, err, "Couldn't read config")

tomlCfg.EthereumChainConfig.GenerateGenesisTimestamp()

err = tomlCfg.Validate()
require.NoError(t, err, "Failed to validate correct TOML config")
require.Equal(t, "trace", *tomlCfg.NodeLogLevel, "Incorrect default log level")
}

func TestEthInvalidLogLevel(t *testing.T) {
t.Parallel()
tomlStr := `
[EthereumNetwork]
consensus_type="pos"
consensus_layer="prysm"
execution_layer="geth"
wait_for_finalization=false
node_log_level="random"
[EthereumNetwork.EthereumChainConfig]
seconds_per_slot=12
slots_per_epoch=2
genesis_delay=20
validator_count=8
chain_id=1234
addresses_to_fund=["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x742d35Cc6634C0532925a3b844Bc454e4438f44f"]
`

tomlCfg, err := readEthereumNetworkConfig(tomlStr)
require.NoError(t, err, "Couldn't read config")

tomlCfg.EthereumChainConfig.GenerateGenesisTimestamp()

err = tomlCfg.Validate()
require.Error(t, err, "Successfully validated incorrect TOML config")
}

type ethereumNetworkWrapper struct {
EthereumNetwork *config.EthereumNetworkConfig `toml:"EthereumNetwork"`
}
Expand Down
19 changes: 19 additions & 0 deletions docker/test_env/geth_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,22 @@ func (g *Geth) getWebsocketEnabledMessage() (string, error) {

return "WebSocket enabled", nil
}

func (g *Geth) logLevelToVerbosity() (int, error) {
switch g.LogLevel {
case "trace":
return 5, nil
case "debug":
return 4, nil
case "info":
return 3, nil
case "warn":
return 2, nil
case "error":
return 1, nil
case "silent":
return 0, nil
default:
return -1, fmt.Errorf("unknown log level: %s", g.LogLevel)
}
}
9 changes: 8 additions & 1 deletion docker/test_env/geth_eth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,12 @@ func (g *Geth) buildEth2dInitScript() (string, error) {
--authrpc.addr=0.0.0.0 --authrpc.jwtsecret={{.JwtFileLocation}} --datadir={{.ExecutionDir}} \
--rpc.allow-unprotected-txs --rpc.txfeecap=0 --allow-insecure-unlock \
--password={{.PasswordFileLocation}} --nodiscover --syncmode=full --networkid={{.ChainID}} \
--graphql --graphql.corsdomain=* --unlock=0x123463a4b065722e99115d6c222f267d9cabb524`
--graphql --graphql.corsdomain=* --unlock=0x123463a4b065722e99115d6c222f267d9cabb524 --verbosity={{.Verbosity}}`

verbosity, err := g.logLevelToVerbosity()
if err != nil {
return "", err
}

data := struct {
HttpPort string
Expand All @@ -142,6 +147,7 @@ func (g *Geth) buildEth2dInitScript() (string, error) {
PasswordFileLocation string
KeystoreDirLocation string
ExecutionDir string
Verbosity int
}{
HttpPort: DEFAULT_EVM_NODE_HTTP_PORT,
WsPort: DEFAULT_EVM_NODE_WS_PORT,
Expand All @@ -151,6 +157,7 @@ func (g *Geth) buildEth2dInitScript() (string, error) {
PasswordFileLocation: ACCOUNT_PASSWORD_FILE_INSIDE_CONTAINER,
KeystoreDirLocation: KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER,
ExecutionDir: "/execution-data",
Verbosity: verbosity,
}

t, err := template.New("init").Parse(initTemplate)
Expand Down
1 change: 1 addition & 0 deletions docker/test_env/nethermind_eth1.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func (g *Nethermind) getEth1ContainerRequest() (*tc.ContainerRequest, error) {
"--Mining.Enabled=true",
"--Init.PeerManagerEnabled=false",
"--HealthChecks.Enabled=true", // default slug /health
fmt.Sprintf("--log=%s", strings.ToUpper(g.LogLevel)),
},
Files: []tc.ContainerFile{
{
Expand Down
1 change: 1 addition & 0 deletions docker/test_env/nethermind_eth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (g *Nethermind) getEth2ContainerRequest() (*tc.ContainerRequest, error) {
"--Network.MaxActivePeers=0",
"--Network.OnlyStaticPeers=true",
"--HealthChecks.Enabled=true", // default slug /health
fmt.Sprintf("--log=%s", strings.ToUpper(g.LogLevel)),
},
Files: []tc.ContainerFile{
{
Expand Down
Loading

0 comments on commit 14d4928

Please sign in to comment.