Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

[Feature] Added support for YAML/YML config file format and configurable server log output to file #525

Merged
merged 10 commits into from
May 10, 2022
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ main

# MacOS Leftovers
.DS_Store
.vscode
.vscode

# exclude build folder
artifacts
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ lint:
.PHONY: generate-bsd-licenses
generate-bsd-licenses:
./generate_dependency_licenses.sh BSD-3-Clause,BSD-2-Clause > ./licenses/bsd_licenses.json

.PHONY: test
test:
go build -o artifacts/polygon-edge .
$(eval export PATH=$(shell pwd)/artifacts:$(PATH))
go test -timeout 28m ./...
Kourin1996 marked this conversation as resolved.
Show resolved Hide resolved
59 changes: 32 additions & 27 deletions command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,55 @@ import (
"strings"

"github.com/0xPolygon/polygon-edge/network"
"gopkg.in/yaml.v3"

"github.com/hashicorp/hcl"
)

// Config defines the server configuration params
type Config struct {
GenesisPath string `json:"chain_config"`
SecretsConfigPath string `json:"secrets_config"`
DataDir string `json:"data_dir"`
BlockGasTarget string `json:"block_gas_target"`
GRPCAddr string `json:"grpc_addr"`
JSONRPCAddr string `json:"jsonrpc_addr"`
Telemetry *Telemetry `json:"telemetry"`
Network *Network `json:"network"`
ShouldSeal bool `json:"seal"`
TxPool *TxPool `json:"tx_pool"`
LogLevel string `json:"log_level"`
RestoreFile string `json:"restore_file"`
BlockTime uint64 `json:"block_time_s"`
Headers *Headers `json:"headers"`
GenesisPath string `json:"chain_config" yaml:"chain_config"`
SecretsConfigPath string `json:"secrets_config" yaml:"secrets_config,omitempty"`
DataDir string `json:"data_dir" yaml:"data_dir"`
BlockGasTarget string `json:"block_gas_target" yaml:"block_gas_target"`
GRPCAddr string `json:"grpc_addr" yaml:"grpc_addr"`
JSONRPCAddr string `json:"jsonrpc_addr" yaml:"jsonrpc_addr"`
Telemetry *Telemetry `json:"telemetry" yaml:"telemetry"`
Network *Network `json:"network" yaml:"network"`
ShouldSeal bool `json:"seal" yaml:"seal"`
TxPool *TxPool `json:"tx_pool" yaml:"tx_pool"`
LogLevel string `json:"log_level" yaml:"log_level"`
RestoreFile string `json:"restore_file" yaml:"restore_file"`
BlockTime uint64 `json:"block_time_s" yaml:"block_time_s"`
Headers *Headers `json:"headers" yaml:"headers"`
LogFilePath string `json:"log_to" yaml:"log_to"`
}

// Telemetry holds the config details for metric services.
type Telemetry struct {
PrometheusAddr string `json:"prometheus_addr"`
PrometheusAddr string `json:"prometheus_addr" yaml:"prometheus_addr"`
}

// Network defines the network configuration params
type Network struct {
NoDiscover bool `json:"no_discover"`
Libp2pAddr string `json:"libp2p_addr"`
NatAddr string `json:"nat_addr"`
DNSAddr string `json:"dns_addr"`
MaxPeers int64 `json:"max_peers,omitempty"`
MaxOutboundPeers int64 `json:"max_outbound_peers,omitempty"`
MaxInboundPeers int64 `json:"max_inbound_peers,omitempty"`
NoDiscover bool `json:"no_discover" yaml:"no_discover"`
Libp2pAddr string `json:"libp2p_addr" yaml:"libp2p_addr"`
NatAddr string `json:"nat_addr" yaml:"nat_addr"`
DNSAddr string `json:"dns_addr" yaml:"dns_addr"`
MaxPeers int64 `json:"max_peers,omitempty" yaml:"max_peers,omitempty"`
MaxOutboundPeers int64 `json:"max_outbound_peers,omitempty" yaml:"max_outbound_peers,omitempty"`
MaxInboundPeers int64 `json:"max_inbound_peers,omitempty" yaml:"max_inbound_peers,omitempty"`
}

// TxPool defines the TxPool configuration params
type TxPool struct {
PriceLimit uint64 `json:"price_limit"`
MaxSlots uint64 `json:"max_slots"`
PriceLimit uint64 `json:"price_limit" yaml:"price_limit"`
MaxSlots uint64 `json:"max_slots" yaml:"max_slots"`
}

// Headers defines the HTTP response headers required to enable CORS.
type Headers struct {
AccessControlAllowOrigins []string `json:"access_control_allow_origins"`
AccessControlAllowOrigins []string `json:"access_control_allow_origins" yaml:"access_control_allow_origins"`
}

// minimum block generation time in seconds
Expand Down Expand Up @@ -85,13 +87,14 @@ func DefaultConfig() *Config {
Headers: &Headers{
AccessControlAllowOrigins: []string{"*"},
},
LogFilePath: "",
}
}

// readConfigFile reads the config file from the specified path, builds a Config object
// and returns it.
//
//Supported file types: .json, .hcl
//Supported file types: .json, .hcl, .yaml, .yml
func readConfigFile(path string) (*Config, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
Expand All @@ -105,8 +108,10 @@ func readConfigFile(path string) (*Config, error) {
unmarshalFunc = hcl.Unmarshal
case strings.HasSuffix(path, ".json"):
unmarshalFunc = json.Unmarshal
case strings.HasSuffix(path, ".yaml"), strings.HasSuffix(path, ".yml"):
unmarshalFunc = yaml.Unmarshal
default:
return nil, fmt.Errorf("suffix of %s is neither hcl nor json", path)
return nil, fmt.Errorf("suffix of %s is neither hcl, json, yaml nor yml", path)
}

config := DefaultConfig()
Expand Down
10 changes: 9 additions & 1 deletion command/server/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package server

import (
"fmt"
"github.com/0xPolygon/polygon-edge/network/common"
"math"
"net"

"github.com/0xPolygon/polygon-edge/network/common"

"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/command/helper"
"github.com/0xPolygon/polygon-edge/network"
Expand Down Expand Up @@ -42,10 +43,17 @@ func (p *serverParams) initRawParams() error {
}

p.initPeerLimits()
p.initLogFileLocation()

return p.initAddresses()
}

func (p *serverParams) initLogFileLocation() {
if p.isLogFileLocationSet() {
p.logFileLocation = p.rawConfig.LogFilePath
}
}

func (p *serverParams) initBlockGasTarget() error {
var parseErr error

Expand Down
11 changes: 10 additions & 1 deletion command/server/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package server

import (
"errors"
"net"

"github.com/0xPolygon/polygon-edge/chain"
"github.com/0xPolygon/polygon-edge/network"
"github.com/0xPolygon/polygon-edge/secrets"
"github.com/0xPolygon/polygon-edge/server"
"github.com/hashicorp/go-hclog"
"github.com/multiformats/go-multiaddr"
"net"
)

const (
Expand All @@ -32,6 +33,7 @@ const (
devIntervalFlag = "dev-interval"
devFlag = "dev"
corsOriginFlag = "access-control-allow-origins"
logFileLocationFlag = "log-to"
)

const (
Expand Down Expand Up @@ -72,6 +74,8 @@ type serverParams struct {

genesisConfig *chain.Chain
secretsConfig *secrets.SecretsManagerConfig

logFileLocation string
}

func (p *serverParams) validateFlags() error {
Expand Down Expand Up @@ -108,6 +112,10 @@ func (p *serverParams) isDNSAddressSet() bool {
return p.rawConfig.Network.DNSAddr != ""
}

func (p *serverParams) isLogFileLocationSet() bool {
return p.rawConfig.LogFilePath != ""
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
}

func (p *serverParams) isDevConsensus() bool {
return server.ConsensusType(p.genesisConfig.Params.GetEngine()) == server.DevConsensus
}
Expand Down Expand Up @@ -159,5 +167,6 @@ func (p *serverParams) generateConfig() *server.Config {
RestoreFile: p.getRestoreFilePath(),
BlockTime: p.rawConfig.BlockTime,
LogLevel: hclog.LevelFromString(p.rawConfig.LogLevel),
LogFilePath: p.logFileLocation,
}
}
7 changes: 7 additions & 0 deletions command/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ func setFlags(cmd *cobra.Command) {
"the CORS header indicating whether any JSON-RPC response can be shared with the specified origin",
)

cmd.Flags().StringVar(
&params.logFileLocation,
logFileLocationFlag,
defaultConfig.LogFilePath,
"write all logs to the file at specified location instead of writing them to console",
)

setDevFlags(cmd)
}

Expand Down
10 changes: 10 additions & 0 deletions example-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
chain_config: test-chain/genesis.json
data_dir: test-chain
jsonrpc_addr: "0.0.0.0:10001"
grpc_addr: "0.0.0.0:20001"
seal: true
network:
libp2p_addr: "127.0.0.1:1478"
log_to: node.log

# for additional parameters check out the docs page: https://edge-docs.polygon.technology/docs/configuration/sample-config
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ require (
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
golang.org/x/tools v0.1.9 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
lukechampine.com/blake3 v1.1.7 // indirect
)
2 changes: 2 additions & 0 deletions server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type Config struct {
SecretsManager *secrets.SecretsManagerConfig

LogLevel hclog.Level

LogFilePath string
}

// Telemetry holds the config details for metric services
Expand Down
56 changes: 47 additions & 9 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import (
"context"
"errors"
"fmt"
"math/big"
"net"
"net/http"
"os"
"path/filepath"

"github.com/0xPolygon/polygon-edge/archive"
"github.com/0xPolygon/polygon-edge/blockchain"
"github.com/0xPolygon/polygon-edge/chain"
Expand All @@ -27,11 +33,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
"math/big"
"net"
"net/http"
"os"
"path/filepath"
)

// Minimal is the central manager of the blockchain client
Expand Down Expand Up @@ -79,12 +80,45 @@ var dirPaths = []string{
"trie",
}

// set log output to the designated file
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
func setLogFileWriter(logFilePath string) (*os.File, error) {
// if file path is empty string return error
if logFilePath == "" {
return nil, fmt.Errorf("log file path not defined")
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
}

logFile, err := os.Create(logFilePath)
if err != nil {
return nil, fmt.Errorf("could not create log file, %w", err)
}

return logFile, nil
}

// create new logger; log to file if log path is defined
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
func newLogger(config *Config) (hclog.Logger, error) {
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
var logFile *os.File

// if there is an error output logs to console
logFile, err := setLogFileWriter(config.LogFilePath)
if err != nil {
return hclog.New(&hclog.LoggerOptions{
Name: "polygon",
Level: config.LogLevel,
}), err
}

// write logs to specified file
return hclog.New(&hclog.LoggerOptions{
Name: "polygon",
Level: config.LogLevel,
Output: logFile,
}), nil
}
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved

// NewServer creates a new Minimal server, using the passed in configuration
func NewServer(config *Config) (*Server, error) {
logger := hclog.New(&hclog.LoggerOptions{
Name: "polygon",
Level: config.LogLevel,
})
logger, logFileErr := newLogger(config)

m := &Server{
logger: logger,
Expand All @@ -94,6 +128,10 @@ func NewServer(config *Config) (*Server, error) {
restoreProgression: progress.NewProgressionWrapper(progress.ChainSyncRestore),
}

if logFileErr != nil {
m.logger.Info("Log file", "fallback to console output err", logFileErr.Error())
}

zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
m.logger.Info("Data dir", "path", config.DataDir)

// Generate all the paths in the dataDir
Expand Down
1 change: 1 addition & 0 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ gopkg.in/square/go-jose.v2/jwt
# gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
gopkg.in/tomb.v1
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
## explicit
gopkg.in/yaml.v3
# lukechampine.com/blake3 v1.1.7
## explicit
Expand Down