func (app *App) SetLogLevel(name, loglevel string) error {
	lvl, ok := app.loggers[name]
	if !ok {
		return fmt.Errorf("cannot find logger %v", name)
	}
	if err := lvl.UnmarshalText([]byte(loglevel)); err != nil {
		return fmt.Errorf("unmarshal text: %w", err)
	}
	return nil
}
SetLogLevel updates the log level of an existing logger.
package node
import (
	"context"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"
	"strconv"
	"time"
	"github.com/mitchellh/mapstructure"
	"github.com/pyroscope-io/pyroscope/pkg/agent/profiler"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"github.com/spacemeshos/go-spacemesh/activation"
	"github.com/spacemeshos/go-spacemesh/api/grpcserver"
	"github.com/spacemeshos/go-spacemesh/blocks"
	cmdp "github.com/spacemeshos/go-spacemesh/cmd"
	"github.com/spacemeshos/go-spacemesh/cmd/mapstructureutil"
	"github.com/spacemeshos/go-spacemesh/common/types"
	"github.com/spacemeshos/go-spacemesh/common/util"
	cfg "github.com/spacemeshos/go-spacemesh/config"
	"github.com/spacemeshos/go-spacemesh/database"
	"github.com/spacemeshos/go-spacemesh/events"
	"github.com/spacemeshos/go-spacemesh/fetch"
	"github.com/spacemeshos/go-spacemesh/filesystem"
	"github.com/spacemeshos/go-spacemesh/hare"
	"github.com/spacemeshos/go-spacemesh/hare/eligibility"
	"github.com/spacemeshos/go-spacemesh/layerfetcher"
	"github.com/spacemeshos/go-spacemesh/layerpatrol"
	"github.com/spacemeshos/go-spacemesh/log"
	"github.com/spacemeshos/go-spacemesh/mempool"
	"github.com/spacemeshos/go-spacemesh/mesh"
	"github.com/spacemeshos/go-spacemesh/metrics"
	"github.com/spacemeshos/go-spacemesh/miner"
	"github.com/spacemeshos/go-spacemesh/p2p"
	"github.com/spacemeshos/go-spacemesh/p2p/pubsub"
	"github.com/spacemeshos/go-spacemesh/pendingtxs"
	"github.com/spacemeshos/go-spacemesh/signing"
	"github.com/spacemeshos/go-spacemesh/svm"
	"github.com/spacemeshos/go-spacemesh/svm/state"
	"github.com/spacemeshos/go-spacemesh/syncer"
	"github.com/spacemeshos/go-spacemesh/system"
	"github.com/spacemeshos/go-spacemesh/timesync"
	timeCfg "github.com/spacemeshos/go-spacemesh/timesync/config"
	"github.com/spacemeshos/go-spacemesh/timesync/peersync"
	"github.com/spacemeshos/go-spacemesh/tortoise"
	"github.com/spacemeshos/go-spacemesh/tortoisebeacon"
	"github.com/spacemeshos/go-spacemesh/tortoisebeacon/weakcoin"
	"github.com/spacemeshos/go-spacemesh/turbohare"
)
const edKeyFileName = "key.bin"
const (
	AppLogger            = "app"
	P2PLogger            = "p2p"
	PostLogger           = "post"
	StateDbLogger        = "stateDbStore"
	StateLogger          = "state"
	AtxDbStoreLogger     = "atxDbStore"
	TBeaconDbStoreLogger = "tbDbStore"
	TBeaconLogger        = "tBeacon"
	WeakCoinLogger       = "weakCoin"
	PoetDbStoreLogger    = "poetDbStore"
	StoreLogger          = "store"
	PoetDbLogger         = "poetDb"
	MeshDBLogger         = "meshDb"
	TrtlLogger           = "trtl"
	AtxDbLogger          = "atxDb"
	BlkEligibilityLogger = "blkElgValidator"
	MeshLogger           = "mesh"
	SyncLogger           = "sync"
	BlockOracle          = "blockOracle"
	HareBeaconLogger     = "hareBeacon"
	HareOracleLogger     = "hareOracle"
	HareLogger           = "hare"
	BlockBuilderLogger   = "blockBuilder"
	BlockListenerLogger  = "blockListener"
	PoetListenerLogger   = "poetListener"
	NipostBuilderLogger  = "nipostBuilder"
	AtxBuilderLogger     = "atxBuilder"
	GossipListener       = "gossipListener"
	Fetcher              = "fetcher"
	LayerFetcher         = "layerFetcher"
	TimeSyncLogger       = "timesync"
	SVMLogger            = "SVM"
)
var Cmd = &cobra.Command{
	Use:   "node",
	Short: "start node",
	Run: func(cmd *cobra.Command, args []string) {
		conf, err := LoadConfigFromFile()
		if err != nil {
			log.With().Error("can't load config file", log.Err(err))
			return
		}
		if err := cmdp.EnsureCLIFlags(cmd, conf); err != nil {
			log.With().Error("can't ensure that cli flags match config value types", log.Err(err))
			return
		}
		if conf.TestMode {
			log.JSONLog(true)
		}
		app := New(
			WithConfig(conf),
			WithLog(log.RegisterHooks(
				log.NewWithLevel("", zap.NewAtomicLevelAt(zapcore.DebugLevel)),
				events.EventHook())),
		)
		starter := func() error {
			if err := app.Initialize(); err != nil {
				log.With().Error("Failed to initialize node.", log.Err(err))
				return fmt.Errorf("init node: %w", err)
			}
			if err := app.Start(); err != nil {
				log.With().Error("Failed to start the node. See logs for details.", log.Err(err))
				return fmt.Errorf("start node: %w", err)
			}
			return nil
		}
		err = starter()
		app.Cleanup()
		if err != nil {
			os.Exit(1)
		}
	},
}
var VersionCmd = &cobra.Command{
	Use:   "version",
	Short: "Show version info",
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Print(cmdp.Version)
		if cmdp.Commit != "" {
			fmt.Printf("+%s", cmdp.Commit)
		}
		fmt.Println()
	},
}
func init() {
	cmdp.AddCommands(Cmd)
	Cmd.AddCommand(VersionCmd)
}
type Service interface {
	Start(ctx context.Context) error
	Close()
}
type HareService interface {
	Service
	GetResult(types.LayerID) ([]types.BlockID, error)
}
type TortoiseBeaconService interface {
	Service
	GetBeacon(id types.EpochID) ([]byte, error)
	HandleSerializedProposalMessage(context.Context, p2p.Peer, []byte) pubsub.ValidationResult
	HandleSerializedFirstVotingMessage(context.Context, p2p.Peer, []byte) pubsub.ValidationResult
	HandleSerializedFollowingVotingMessage(context.Context, p2p.Peer, []byte) pubsub.ValidationResult
}
type TickProvider interface {
	Subscribe() timesync.LayerTimer
	Unsubscribe(timesync.LayerTimer)
	GetCurrentLayer() types.LayerID
	StartNotifying()
	GetGenesisTime() time.Time
	LayerToTime(types.LayerID) time.Time
	Close()
	AwaitLayer(types.LayerID) chan struct{}
}
func LoadConfigFromFile() (*cfg.Config, error) {
	fileLocation := viper.GetString("config")
	vip := viper.New()
	if err := cfg.LoadConfig(fileLocation, vip); err != nil {
		log.Error(fmt.Sprintf("couldn't load config file at location: %s switching to defaults \n error: %v.",
			fileLocation, err))
	}
	conf := cfg.DefaultConfig()
	hook := mapstructure.ComposeDecodeHookFunc(
		mapstructure.StringToTimeDurationHookFunc(),
		mapstructure.StringToSliceHookFunc(","),
		mapstructureutil.BigRatDecodeFunc(),
	)
	if err := vip.Unmarshal(&conf, viper.DecodeHook(hook)); err != nil {
		log.With().Error("Failed to parse config", log.Err(err))
		return nil, fmt.Errorf("unmarshal viper: %w", err)
	}
	return &conf, nil
}
type Option func(app *App)
func WithLog(logger log.Log) Option {
	return func(app *App) {
		app.log = logger
	}
}
func WithConfig(conf *cfg.Config) Option {
	return func(app *App) {
		app.Config = conf
	}
}
func New(opts ...Option) *App {
	defaultConfig := cfg.DefaultConfig()
	app := &App{
		Config:  &defaultConfig,
		log:     log.NewNop(),
		loggers: make(map[string]*zap.AtomicLevel),
		term:    make(chan struct{}),
		started: make(chan struct{}),
	}
	for _, opt := range opts {
		opt(app)
	}
	lvl := zap.NewAtomicLevelAt(zap.InfoLevel)
	log.SetupGlobal(app.log.SetLevel(&lvl))
	return app
}
type App struct {
	*cobra.Command
	nodeID         types.NodeID
	Config         *cfg.Config
	grpcAPIService *grpcserver.Server
	jsonAPIService *grpcserver.JSONHTTPServer
	gatewaySvc     *grpcserver.GatewayService
	globalstateSvc *grpcserver.GlobalStateService
	txService      *grpcserver.TransactionService
	syncer         *syncer.Syncer
	blockListener  *blocks.BlockHandler
	state          *state.TransactionProcessor
	blockProducer  *miner.BlockBuilder
	oracle         *blocks.Oracle
	txProcessor    *state.TransactionProcessor
	mesh           *mesh.Mesh
	clock          TickProvider
	hare           HareService
	postSetupMgr   *activation.PostSetupManager
	atxBuilder     *activation.Builder
	atxDb          *activation.DB
	poetListener   *activation.PoetListener
	edSgn          *signing.EdSigner
	tortoiseBeacon TortoiseBeaconService
	closers        []interface{ Close() }
	log            log.Log
	txPool         *mempool.TxMempool
	svm            *svm.SVM
	layerFetch     *layerfetcher.Logic
	ptimesync      *peersync.Sync
	host *p2p.Host
	loggers map[string]*zap.AtomicLevel
	term    chan struct{}  
	started chan struct{}  
}
func (app *App) introduction() {
	log.Info("Welcome to Spacemesh. Spacemesh full node is starting...")
}
func (app *App) Initialize() (err error) {
	timeCfg.TimeConfigValues = app.Config.TIME
	err = filesystem.ExistOrCreate(app.Config.DataDir())
	if err != nil {
		return fmt.Errorf("ensure folders exist: %w", err)
	}
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)
	go func() {
		for range signalChan {
			app.log.Info("Received an interrupt, stopping services...\n")
			cmdp.Cancel()
		}
	}()
	app.setupLogging()
	app.introduction()
	drift, err := timesync.CheckSystemClockDrift()
	if err != nil {
		return fmt.Errorf("check system clock drift: %w", err)
	}
	log.Info("System clock synchronized with ntp. drift: %s", drift)
	return nil
}
func (app *App) setupLogging() {
	log.Info("%s", app.getAppInfo())
	msg := "initializing event reporter"
	if app.Config.PublishEventsURL != "" {
		msg += fmt.Sprintf(" with pubsub URL: %s", app.Config.PublishEventsURL)
	}
	log.Info(msg)
	if err := events.InitializeEventReporter(app.Config.PublishEventsURL); err != nil {
		log.With().Error("unable to initialize event reporter", log.Err(err))
	}
}
func (app *App) getAppInfo() string {
	return fmt.Sprintf("App version: %s. Git: %s - %s . Go Version: %s. OS: %s-%s ",
		cmdp.Version, cmdp.Branch, cmdp.Commit, runtime.Version(), runtime.GOOS, runtime.GOARCH)
}
func (app *App) Cleanup() {
	log.Info("app cleanup starting...")
	app.stopServices()
	log.Info("app cleanup completed")
}
func (app *App) addLogger(name string, logger log.Log) log.Log {
	lvl := zap.NewAtomicLevel()
	config := app.Config.LOGGING
	level, ok := map[string]string{
		AppLogger:            config.AppLoggerLevel,
		P2PLogger:            config.P2PLoggerLevel,
		PostLogger:           config.PostLoggerLevel,
		StateDbLogger:        config.StateDbLoggerLevel,
		StateLogger:          config.StateLoggerLevel,
		AtxDbStoreLogger:     config.AtxDbStoreLoggerLevel,
		TBeaconLogger:        config.TBeaconLoggerLevel,
		WeakCoinLogger:       config.WeakCoinLoggerLevel,
		PoetDbStoreLogger:    config.PoetDbStoreLoggerLevel,
		StoreLogger:          config.StoreLoggerLevel,
		PoetDbLogger:         config.PoetDbLoggerLevel,
		MeshDBLogger:         config.MeshDBLoggerLevel,
		TrtlLogger:           config.TrtlLoggerLevel,
		AtxDbLogger:          config.AtxDbLoggerLevel,
		BlkEligibilityLogger: config.BlkEligibilityLoggerLevel,
		MeshLogger:           config.MeshLoggerLevel,
		SyncLogger:           config.SyncLoggerLevel,
		BlockOracle:          config.BlockOracleLevel,
		HareOracleLogger:     config.HareOracleLoggerLevel,
		HareBeaconLogger:     config.HareBeaconLoggerLevel,
		HareLogger:           config.HareLoggerLevel,
		BlockBuilderLogger:   config.BlockBuilderLoggerLevel,
		BlockListenerLogger:  config.BlockListenerLoggerLevel,
		PoetListenerLogger:   config.PoetListenerLoggerLevel,
		NipostBuilderLogger:  config.NipostBuilderLoggerLevel,
		AtxBuilderLogger:     config.AtxBuilderLoggerLevel,
		TimeSyncLogger:       config.TimeSyncLoggerLevel,
	}[name]
	if ok {
		if err := lvl.UnmarshalText([]byte(level)); err != nil {
			app.log.Error("cannot parse logging for %v error %v", name, err)
			lvl.SetLevel(log.Level())
		}
	} else {
		lvl.SetLevel(log.Level())
	}
	if logger.Check(lvl.Level()) {
		app.loggers[name] = &lvl
		logger = logger.SetLevel(&lvl)
	}
	return logger.WithName(name).WithFields(log.String("module", name))
}