mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 19:50:36 +00:00
79ed8cad35
This change introduces additional processes to manage snapshot uploading for E2 snapshots: ## erigon snapshots upload The `snapshots uploader` command starts a version of erigon customized for uploading snapshot files to a remote location. It breaks the stage execution process after the senders stage and then uses the snapshot stage to send uploaded headers, bodies and (in the case of polygon) bor spans and events to snapshot files. Because this process avoids execution in run signifigantly faster than a standard erigon configuration. The uploader uses rclone to send seedable (100K or 500K blocks) to a remote storage location specified in the rclone config file. The **uploader** is configured to minimize disk usage by doing the following: * It removes snapshots once they are loaded * It aggressively prunes the database once entities are transferred to snapshots in addition to this it has the following performance related features: * maximizes the workers allocated to snapshot processing to improve throughput * Can be started from scratch by downloading the latest snapshots from the remote location to seed processing ## snapshots command Is a stand alone command for managing remote snapshots it has the following sub commands * **cmp** - compare snapshots * **copy** - copy snapshots * **verify** - verify snapshots * **manifest** - manage the manifest file in the root of remote snapshot locations * **torrent** - manage snapshot torrent files
229 lines
7.0 KiB
Go
229 lines
7.0 KiB
Go
package logging
|
|
|
|
import (
|
|
"flag"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"github.com/ledgerwatch/log/v3"
|
|
"github.com/spf13/cobra"
|
|
"github.com/urfave/cli/v2"
|
|
"gopkg.in/natefinch/lumberjack.v2"
|
|
)
|
|
|
|
// SetupLoggerCtx performs the logging setup according to the parameters
|
|
// containted in the given urfave context. It returns either root logger,
|
|
// if rootHandler argument is set to true, or a newly created logger.
|
|
// This is to ensure gradual transition to the use of non-root logger thoughout
|
|
// the erigon code without a huge change at once.
|
|
// This function which is used in Erigon itself.
|
|
// Note: urfave and cobra are two CLI frameworks/libraries for the same functionalities
|
|
// and it would make sense to choose one over another
|
|
func SetupLoggerCtx(filePrefix string, ctx *cli.Context,
|
|
consoleDefaultLevel log.Lvl, dirDefaultLevel log.Lvl, rootHandler bool) log.Logger {
|
|
var consoleJson = ctx.Bool(LogJsonFlag.Name) || ctx.Bool(LogConsoleJsonFlag.Name)
|
|
var dirJson = ctx.Bool(LogDirJsonFlag.Name)
|
|
|
|
consoleLevel, lErr := tryGetLogLevel(ctx.String(LogConsoleVerbosityFlag.Name))
|
|
if lErr != nil {
|
|
// try verbosity flag
|
|
consoleLevel, lErr = tryGetLogLevel(ctx.String(LogVerbosityFlag.Name))
|
|
if lErr != nil {
|
|
consoleLevel = consoleDefaultLevel
|
|
}
|
|
}
|
|
|
|
dirLevel, dErr := tryGetLogLevel(ctx.String(LogDirVerbosityFlag.Name))
|
|
if dErr != nil {
|
|
dirLevel = dirDefaultLevel
|
|
}
|
|
|
|
dirPath := ""
|
|
if !ctx.Bool(LogDirDisableFlag.Name) && dirPath != "/dev/null" {
|
|
dirPath = ctx.String(LogDirPathFlag.Name)
|
|
if dirPath == "" {
|
|
datadir := ctx.String("datadir")
|
|
if datadir != "" {
|
|
dirPath = filepath.Join(datadir, "logs")
|
|
}
|
|
}
|
|
if logDirPrefix := ctx.String(LogDirPrefixFlag.Name); len(logDirPrefix) > 0 {
|
|
filePrefix = logDirPrefix
|
|
}
|
|
}
|
|
|
|
var logger log.Logger
|
|
if rootHandler {
|
|
logger = log.Root()
|
|
} else {
|
|
logger = log.New()
|
|
}
|
|
|
|
initSeparatedLogging(logger, filePrefix, dirPath, consoleLevel, dirLevel, consoleJson, dirJson)
|
|
return logger
|
|
}
|
|
|
|
// SetupLoggerCmd perform the logging for a cobra command, and sets it to the root logger
|
|
// This is the function which is NOT used by Erigon itself, but instead by some cobra-based commands,
|
|
// for example, rpcdaemon or integration.
|
|
// Note: urfave and cobra are two CLI frameworks/libraries for the same functionalities
|
|
// and it would make sense to choose one over another
|
|
func SetupLoggerCmd(filePrefix string, cmd *cobra.Command) log.Logger {
|
|
|
|
logJsonVal, ljerr := cmd.Flags().GetBool(LogJsonFlag.Name)
|
|
if ljerr != nil {
|
|
logJsonVal = false
|
|
}
|
|
|
|
logConsoleJsonVal, lcjerr := cmd.Flags().GetBool(LogConsoleJsonFlag.Name)
|
|
if lcjerr != nil {
|
|
logConsoleJsonVal = false
|
|
}
|
|
|
|
var consoleJson = logJsonVal || logConsoleJsonVal
|
|
dirJson, djerr := cmd.Flags().GetBool(LogDirJsonFlag.Name)
|
|
if djerr != nil {
|
|
dirJson = false
|
|
}
|
|
|
|
consoleLevel, lErr := tryGetLogLevel(cmd.Flags().Lookup(LogConsoleVerbosityFlag.Name).Value.String())
|
|
if lErr != nil {
|
|
// try verbosity flag
|
|
consoleLevel, lErr = tryGetLogLevel(cmd.Flags().Lookup(LogVerbosityFlag.Name).Value.String())
|
|
if lErr != nil {
|
|
consoleLevel = log.LvlInfo
|
|
}
|
|
}
|
|
|
|
dirLevel, dErr := tryGetLogLevel(cmd.Flags().Lookup(LogDirVerbosityFlag.Name).Value.String())
|
|
if dErr != nil {
|
|
dirLevel = log.LvlInfo
|
|
}
|
|
|
|
dirPath := ""
|
|
disableFileLogging, err := cmd.Flags().GetBool(LogDirDisableFlag.Name)
|
|
if err != nil {
|
|
disableFileLogging = false
|
|
}
|
|
if !disableFileLogging && dirPath != "/dev/null" {
|
|
dirPath = cmd.Flags().Lookup(LogDirPathFlag.Name).Value.String()
|
|
if dirPath == "" {
|
|
datadirFlag := cmd.Flags().Lookup("datadir")
|
|
if datadirFlag != nil {
|
|
datadir := datadirFlag.Value.String()
|
|
if datadir != "" {
|
|
dirPath = filepath.Join(datadir, "logs")
|
|
}
|
|
}
|
|
}
|
|
if logDirPrefix := cmd.Flags().Lookup(LogDirPrefixFlag.Name).Value.String(); len(logDirPrefix) > 0 {
|
|
filePrefix = logDirPrefix
|
|
}
|
|
}
|
|
|
|
initSeparatedLogging(log.Root(), filePrefix, dirPath, consoleLevel, dirLevel, consoleJson, dirJson)
|
|
return log.Root()
|
|
}
|
|
|
|
// SetupLoggerCmd perform the logging using parametrs specifying by `flag` package, and sets it to the root logger
|
|
// This is the function which is NOT used by Erigon itself, but instead by utility commans
|
|
func SetupLogger(filePrefix string) log.Logger {
|
|
var logConsoleVerbosity = flag.String(LogConsoleVerbosityFlag.Name, "", LogConsoleVerbosityFlag.Usage)
|
|
var logDirVerbosity = flag.String(LogDirVerbosityFlag.Name, "", LogDirVerbosityFlag.Usage)
|
|
var logDirPath = flag.String(LogDirPathFlag.Name, "", LogDirPathFlag.Usage)
|
|
var logDirPrefix = flag.String(LogDirPrefixFlag.Name, "", LogDirPrefixFlag.Usage)
|
|
var logVerbosity = flag.String(LogVerbosityFlag.Name, "", LogVerbosityFlag.Usage)
|
|
var logConsoleJson = flag.Bool(LogConsoleJsonFlag.Name, false, LogConsoleJsonFlag.Usage)
|
|
var logJson = flag.Bool(LogJsonFlag.Name, false, LogJsonFlag.Usage)
|
|
var logDirJson = flag.Bool(LogDirJsonFlag.Name, false, LogDirJsonFlag.Usage)
|
|
flag.Parse()
|
|
|
|
var consoleJson = *logJson || *logConsoleJson
|
|
var dirJson = logDirJson
|
|
|
|
consoleLevel, lErr := tryGetLogLevel(*logConsoleVerbosity)
|
|
if lErr != nil {
|
|
// try verbosity flag
|
|
consoleLevel, lErr = tryGetLogLevel(*logVerbosity)
|
|
if lErr != nil {
|
|
consoleLevel = log.LvlInfo
|
|
}
|
|
}
|
|
|
|
dirLevel, dErr := tryGetLogLevel(*logDirVerbosity)
|
|
if dErr != nil {
|
|
dirLevel = log.LvlInfo
|
|
}
|
|
|
|
if logDirPrefix != nil && len(*logDirPrefix) > 0 {
|
|
filePrefix = *logDirPrefix
|
|
}
|
|
|
|
initSeparatedLogging(log.Root(), filePrefix, *logDirPath, consoleLevel, dirLevel, consoleJson, *dirJson)
|
|
return log.Root()
|
|
}
|
|
|
|
// initSeparatedLogging construct a log handler accrosing to the configuration parameters passed to it
|
|
// and sets the constructed handler to be the handler of the given logger. It then uses that logger
|
|
// to report the status of this initialisation
|
|
func initSeparatedLogging(
|
|
logger log.Logger,
|
|
filePrefix string,
|
|
dirPath string,
|
|
consoleLevel log.Lvl,
|
|
dirLevel log.Lvl,
|
|
consoleJson bool,
|
|
dirJson bool) {
|
|
|
|
var consoleHandler log.Handler
|
|
|
|
if consoleJson {
|
|
consoleHandler = log.LvlFilterHandler(consoleLevel, log.StreamHandler(os.Stderr, log.JsonFormat()))
|
|
} else {
|
|
consoleHandler = log.LvlFilterHandler(consoleLevel, log.StderrHandler)
|
|
}
|
|
logger.SetHandler(consoleHandler)
|
|
|
|
if len(dirPath) == 0 {
|
|
logger.Info("console logging only")
|
|
return
|
|
}
|
|
|
|
err := os.MkdirAll(dirPath, 0764)
|
|
if err != nil {
|
|
logger.Warn("failed to create log dir, console logging only")
|
|
return
|
|
}
|
|
|
|
dirFormat := log.TerminalFormatNoColor()
|
|
if dirJson {
|
|
dirFormat = log.JsonFormat()
|
|
}
|
|
|
|
lumberjack := &lumberjack.Logger{
|
|
Filename: filepath.Join(dirPath, filePrefix+".log"),
|
|
MaxSize: 100, // megabytes
|
|
MaxBackups: 3,
|
|
MaxAge: 28, //days
|
|
}
|
|
userLog := log.StreamHandler(lumberjack, dirFormat)
|
|
|
|
mux := log.MultiHandler(consoleHandler, log.LvlFilterHandler(dirLevel, userLog))
|
|
logger.SetHandler(mux)
|
|
logger.Info("logging to file system", "log dir", dirPath, "file prefix", filePrefix, "log level", dirLevel, "json", dirJson)
|
|
return
|
|
}
|
|
|
|
func tryGetLogLevel(s string) (log.Lvl, error) {
|
|
lvl, err := log.LvlFromString(s)
|
|
if err != nil {
|
|
l, err := strconv.Atoi(s)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return log.Lvl(l), nil
|
|
}
|
|
return lvl, nil
|
|
}
|