feat!: build: separate miner and node version strings

Ref: https://github.com/filecoin-project/lotus/issues/12010
This commit is contained in:
Rod Vagg 2024-05-23 15:42:43 +10:00
parent cf8d187817
commit 0a51a0a219
25 changed files with 72 additions and 37 deletions

View File

@ -106,7 +106,7 @@ func NewLotusOpenRPCDocument(Comments, GroupDocs map[string]string) *go_openrpc_
title := "Lotus RPC API" title := "Lotus RPC API"
info.Title = (*meta_schema.InfoObjectProperties)(&title) info.Title = (*meta_schema.InfoObjectProperties)(&title)
version := build.BuildVersion version := build.NodeBuildVersion
info.Version = (*meta_schema.InfoObjectVersion)(&version) info.Version = (*meta_schema.InfoObjectVersion)(&version)
return info return info
}, },

View File

@ -28,13 +28,31 @@ var PanicReportingPath = "panic-reports"
// the lotus journal to be included in the panic report. // the lotus journal to be included in the panic report.
var PanicReportJournalTail = defaultJournalTail var PanicReportJournalTail = defaultJournalTail
// GeneratePanicReport produces a timestamped dump of the application state // GenerateNodePanicReport produces a timestamped dump of the application state
// for inspection and debugging purposes. Call this function from any place // for inspection and debugging purposes. Call this function from any place
// where a panic or severe error needs to be examined. `persistPath` is the // where a panic or severe error needs to be examined. `persistPath` is the
// path where the reports should be saved. `repoPath` is the path where the // path where the reports should be saved. `repoPath` is the path where the
// journal should be read from. `label` is an optional string to include // journal should be read from. `label` is an optional string to include
// next to the report timestamp. // next to the report timestamp.
func GeneratePanicReport(persistPath, repoPath, label string) { //
// This function should be called for panics originating from the Lotus daemon.
func GenerateNodePanicReport(persistPath, repoPath, label string) {
generatePanicReport(NodeUserVersion(), persistPath, repoPath, label)
}
// GenerateMinerPanicReport produces a timestamped dump of the application state
// for inspection and debugging purposes. Call this function from any place
// where a panic or severe error needs to be examined. `persistPath` is the
// path where the reports should be saved. `repoPath` is the path where the
// journal should be read from. `label` is an optional string to include
// next to the report timestamp.
//
// This function should be called for panics originating from the Lotus miner.
func GenerateMinerPanicReport(persistPath, repoPath, label string) {
generatePanicReport(MinerUserVersion(), persistPath, repoPath, label)
}
func generatePanicReport(buildVersion BuildVersion, persistPath, repoPath, label string) {
// make sure we always dump the latest logs on the way out // make sure we always dump the latest logs on the way out
// especially since we're probably panicking // especially since we're probably panicking
defer panicLog.Sync() //nolint:errcheck defer panicLog.Sync() //nolint:errcheck
@ -64,21 +82,21 @@ func GeneratePanicReport(persistPath, repoPath, label string) {
return return
} }
writeAppVersion(filepath.Join(reportPath, "version")) writeAppVersion(buildVersion, filepath.Join(reportPath, "version"))
writeStackTrace(filepath.Join(reportPath, "stacktrace.dump")) writeStackTrace(filepath.Join(reportPath, "stacktrace.dump"))
writeProfile("goroutines", filepath.Join(reportPath, "goroutines.pprof.gz")) writeProfile("goroutines", filepath.Join(reportPath, "goroutines.pprof.gz"))
writeProfile("heap", filepath.Join(reportPath, "heap.pprof.gz")) writeProfile("heap", filepath.Join(reportPath, "heap.pprof.gz"))
writeJournalTail(PanicReportJournalTail, repoPath, filepath.Join(reportPath, "journal.ndjson")) writeJournalTail(PanicReportJournalTail, repoPath, filepath.Join(reportPath, "journal.ndjson"))
} }
func writeAppVersion(file string) { func writeAppVersion(buildVersion BuildVersion, file string) {
f, err := os.Create(file) f, err := os.Create(file)
if err != nil { if err != nil {
panicLog.Error(err.Error()) panicLog.Error(err.Error())
} }
defer f.Close() //nolint:errcheck defer f.Close() //nolint:errcheck
versionString := []byte(BuildVersion + BuildTypeString() + CurrentCommit + "\n") versionString := []byte(string(buildVersion) + BuildTypeString() + CurrentCommit + "\n")
if _, err := f.Write(versionString); err != nil { if _, err := f.Write(versionString); err != nil {
panicLog.Error(err.Error()) panicLog.Error(err.Error())
} }

View File

@ -2,6 +2,8 @@ package build
import "os" import "os"
type BuildVersion string
var CurrentCommit string var CurrentCommit string
var BuildType int var BuildType int
@ -36,13 +38,24 @@ func BuildTypeString() string {
} }
} }
// BuildVersion is the local build version // NodeBuildVersion is the local build version of the Lotus daemon
const BuildVersion = "1.27.1-dev" const NodeBuildVersion string = "1.27.1-dev"
func UserVersion() string { func NodeUserVersion() BuildVersion {
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
return BuildVersion return BuildVersion(NodeBuildVersion)
} }
return BuildVersion + BuildTypeString() + CurrentCommit return BuildVersion(NodeBuildVersion + BuildTypeString() + CurrentCommit)
}
// MinerBuildVersion is the local build version of the Lotus miner
const MinerBuildVersion = "1.27.1-dev"
func MinerUserVersion() BuildVersion {
if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" {
return BuildVersion(MinerBuildVersion)
}
return BuildVersion(MinerBuildVersion + BuildTypeString() + CurrentCommit)
} }

View File

@ -97,7 +97,7 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
if err != nil { if err != nil {
return nil, xerrors.Errorf("could not create http drand client: %w", err) return nil, xerrors.Errorf("could not create http drand client: %w", err)
} }
hc.(DrandHTTPClient).SetUserAgent("drand-client-lotus/" + build.BuildVersion) hc.(DrandHTTPClient).SetUserAgent("drand-client-lotus/" + build.NodeBuildVersion)
clients = append(clients, hc) clients = append(clients, hc)
} }

View File

@ -100,7 +100,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-bench", Name: "lotus-bench",
Usage: "Benchmark performance of lotus on your hardware", Usage: "Benchmark performance of lotus on your hardware",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
DisableSliceFlagSeparator: true, DisableSliceFlagSeparator: true,
Commands: []*cli.Command{ Commands: []*cli.Command{
proveCmd, proveCmd,

View File

@ -41,7 +41,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-fountain", Name: "lotus-fountain",
Usage: "Devnet token distribution utility", Usage: "Devnet token distribution utility",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "repo", Name: "repo",

View File

@ -40,7 +40,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-gateway", Name: "lotus-gateway",
Usage: "Public API server for lotus", Usage: "Public API server for lotus",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "repo", Name: "repo",

View File

@ -36,7 +36,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-health", Name: "lotus-health",
Usage: "Tools for monitoring lotus daemon health", Usage: "Tools for monitoring lotus daemon health",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Commands: local, Commands: local,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{

View File

@ -101,7 +101,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-miner", Name: "lotus-miner",
Usage: "Filecoin decentralized storage network miner", Usage: "Filecoin decentralized storage network miner",
Version: build.UserVersion(), Version: string(build.MinerUserVersion()),
EnableBashCompletion: true, EnableBashCompletion: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
@ -159,7 +159,7 @@ func main() {
After: func(c *cli.Context) error { After: func(c *cli.Context) error {
if r := recover(); r != nil { if r := recover(); r != nil {
// Generate report in LOTUS_PATH and re-raise panic // Generate report in LOTUS_PATH and re-raise panic
build.GeneratePanicReport(c.String("panic-reports"), c.String(FlagMinerRepo), c.App.Name) build.GenerateMinerPanicReport(c.String("panic-reports"), c.String(FlagMinerRepo), c.App.Name)
panic(r) panic(r)
} }
return nil return nil

View File

@ -57,7 +57,7 @@ var runCmd = &cli.Command{
} }
ctx, _ := tag.New(lcli.DaemonContext(cctx), ctx, _ := tag.New(lcli.DaemonContext(cctx),
tag.Insert(metrics.Version, build.BuildVersion), tag.Insert(metrics.Version, build.MinerBuildVersion),
tag.Insert(metrics.Commit, build.CurrentCommit), tag.Insert(metrics.Commit, build.CurrentCommit),
tag.Insert(metrics.NodeType, "miner"), tag.Insert(metrics.NodeType, "miner"),
) )

View File

@ -70,7 +70,7 @@ func main() {
A single message will be produced per miner totaling their refund for all PreCommitSector messages A single message will be produced per miner totaling their refund for all PreCommitSector messages
in a tipset. in a tipset.
`, `,
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "lotus-path", Name: "lotus-path",

View File

@ -38,7 +38,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-seed", Name: "lotus-seed",
Usage: "Seal sectors for genesis miner", Usage: "Seal sectors for genesis miner",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "sector-dir", Name: "sector-dir",

View File

@ -97,7 +97,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-shed", Name: "lotus-shed",
Usage: "A place for all the lotus tools", Usage: "A place for all the lotus tools",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Commands: local, Commands: local,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{

View File

@ -42,7 +42,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-stats", Name: "lotus-stats",
Usage: "Collect basic information about a filecoin network using lotus", Usage: "Collect basic information about a filecoin network using lotus",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: "lotus-path", Name: "lotus-path",

View File

@ -52,7 +52,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-wallet", Name: "lotus-wallet",
Usage: "Basic external wallet", Usage: "Basic external wallet",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
Description: ` Description: `
lotus-wallet provides a remote wallet service for lotus. lotus-wallet provides a remote wallet service for lotus.

View File

@ -70,7 +70,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus-worker", Name: "lotus-worker",
Usage: "Remote miner worker", Usage: "Remote miner worker",
Version: build.UserVersion(), Version: string(build.MinerUserVersion()),
EnableBashCompletion: true, EnableBashCompletion: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
@ -104,7 +104,7 @@ func main() {
After: func(c *cli.Context) error { After: func(c *cli.Context) error {
if r := recover(); r != nil { if r := recover(); r != nil {
// Generate report in LOTUS_PANIC_REPORT_PATH and re-raise panic // Generate report in LOTUS_PANIC_REPORT_PATH and re-raise panic
build.GeneratePanicReport(c.String("panic-reports"), c.String(FlagWorkerRepo), c.App.Name) build.GenerateMinerPanicReport(c.String("panic-reports"), c.String(FlagWorkerRepo), c.App.Name)
panic(r) panic(r)
} }
return nil return nil

View File

@ -209,7 +209,7 @@ var DaemonCmd = &cli.Command{
} }
ctx, _ := tag.New(context.Background(), ctx, _ := tag.New(context.Background(),
tag.Insert(metrics.Version, build.BuildVersion), tag.Insert(metrics.Version, build.NodeBuildVersion),
tag.Insert(metrics.Commit, build.CurrentCommit), tag.Insert(metrics.Commit, build.CurrentCommit),
tag.Insert(metrics.NodeType, "chain"), tag.Insert(metrics.NodeType, "chain"),
) )

View File

@ -72,7 +72,7 @@ func main() {
app := &cli.App{ app := &cli.App{
Name: "lotus", Name: "lotus",
Usage: "Filecoin decentralized storage network client", Usage: "Filecoin decentralized storage network client",
Version: build.UserVersion(), Version: string(build.NodeUserVersion()),
EnableBashCompletion: true, EnableBashCompletion: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
@ -107,7 +107,7 @@ func main() {
After: func(c *cli.Context) error { After: func(c *cli.Context) error {
if r := recover(); r != nil { if r := recover(); r != nil {
// Generate report in LOTUS_PATH and re-raise panic // Generate report in LOTUS_PATH and re-raise panic
build.GeneratePanicReport(c.String("panic-reports"), c.String("repo"), c.App.Name) build.GenerateNodePanicReport(c.String("panic-reports"), c.String("repo"), c.App.Name)
panic(r) panic(r)
} }
return nil return nil

View File

@ -74,7 +74,7 @@ func (ts *apiSuite) testVersion(t *testing.T) {
versions := strings.Split(v.Version, "+") versions := strings.Split(v.Version, "+")
require.NotZero(t, len(versions), "empty version") require.NotZero(t, len(versions), "empty version")
require.Equal(t, versions[0], build.BuildVersion) require.Equal(t, versions[0], build.NodeBuildVersion)
} }
func (ts *apiSuite) testID(t *testing.T) { func (ts *apiSuite) testID(t *testing.T) {

View File

@ -266,12 +266,13 @@ func Base() Option {
} }
// Config sets up constructors based on the provided Config // Config sets up constructors based on the provided Config
func ConfigCommon(cfg *config.Common, enableLibp2pNode bool) Option { func ConfigCommon(cfg *config.Common, buildVersion build.BuildVersion, enableLibp2pNode bool) Option {
// setup logging early // setup logging early
lotuslog.SetLevelsFromConfig(cfg.Logging.SubsystemLevels) lotuslog.SetLevelsFromConfig(cfg.Logging.SubsystemLevels)
return Options( return Options(
func(s *Settings) error { s.Config = true; return nil }, func(s *Settings) error { s.Config = true; return nil },
Override(new(build.BuildVersion), buildVersion),
Override(new(dtypes.APIEndpoint), func() (dtypes.APIEndpoint, error) { Override(new(dtypes.APIEndpoint), func() (dtypes.APIEndpoint, error) {
return multiaddr.NewMultiaddr(cfg.API.ListenAddress) return multiaddr.NewMultiaddr(cfg.API.ListenAddress)
}), }),

View File

@ -12,6 +12,7 @@ import (
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/beacon"
"github.com/filecoin-project/lotus/chain/consensus" "github.com/filecoin-project/lotus/chain/consensus"
@ -184,7 +185,7 @@ func ConfigFullNode(c interface{}) Option {
enableLibp2pNode := true // always enable libp2p for full nodes enableLibp2pNode := true // always enable libp2p for full nodes
return Options( return Options(
ConfigCommon(&cfg.Common, enableLibp2pNode), ConfigCommon(&cfg.Common, build.NodeUserVersion(), enableLibp2pNode),
Override(new(dtypes.UniversalBlockstore), modules.UniversalBlockstore), Override(new(dtypes.UniversalBlockstore), modules.UniversalBlockstore),

View File

@ -84,7 +84,7 @@ func ConfigStorageMiner(c interface{}) Option {
Override(new(dtypes.DrandSchedule), modules.BuiltinDrandConfig), Override(new(dtypes.DrandSchedule), modules.BuiltinDrandConfig),
Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap), Override(new(dtypes.BootstrapPeers), modules.BuiltinBootstrap),
Override(new(dtypes.DrandBootstrap), modules.DrandBootstrap), Override(new(dtypes.DrandBootstrap), modules.DrandBootstrap),
ConfigCommon(&cfg.Common, enableLibp2pNode), ConfigCommon(&cfg.Common, build.NodeUserVersion(), enableLibp2pNode),
Override(CheckFDLimit, modules.CheckFdLimit(build.MinerFDLimit)), // recommend at least 100k FD limit to miners Override(CheckFDLimit, modules.CheckFdLimit(build.MinerFDLimit)), // recommend at least 100k FD limit to miners

View File

@ -24,6 +24,8 @@ var session = uuid.New()
type CommonAPI struct { type CommonAPI struct {
fx.In fx.In
BuildVersion build.BuildVersion
Alerting *alerting.Alerting Alerting *alerting.Alerting
APISecret *dtypes.APIAlg APISecret *dtypes.APIAlg
ShutdownChan dtypes.ShutdownChan ShutdownChan dtypes.ShutdownChan
@ -63,7 +65,7 @@ func (a *CommonAPI) Version(context.Context) (api.APIVersion, error) {
} }
return api.APIVersion{ return api.APIVersion{
Version: build.UserVersion(), Version: string(a.BuildVersion),
APIVersion: v, APIVersion: v,
BlockDelay: build.BlockDelaySecs, BlockDelay: build.BlockDelaySecs,

View File

@ -836,7 +836,7 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.Et
} }
func (a *EthModule) Web3ClientVersion(ctx context.Context) (string, error) { func (a *EthModule) Web3ClientVersion(ctx context.Context) (string, error) {
return build.UserVersion(), nil return string(build.NodeUserVersion()), nil
} }
func (a *EthModule) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error) { func (a *EthModule) EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error) {

View File

@ -38,7 +38,7 @@ func Peerstore() (peerstore.Peerstore, error) {
return pstoremem.NewPeerstore() return pstoremem.NewPeerstore()
} }
func Host(mctx helpers.MetricsCtx, lc fx.Lifecycle, params P2PHostIn) (RawHost, error) { func Host(mctx helpers.MetricsCtx, buildVersion build.BuildVersion, lc fx.Lifecycle, params P2PHostIn) (RawHost, error) {
pkey := params.Peerstore.PrivKey(params.ID) pkey := params.Peerstore.PrivKey(params.ID)
if pkey == nil { if pkey == nil {
return nil, fmt.Errorf("missing private key for node ID: %s", params.ID) return nil, fmt.Errorf("missing private key for node ID: %s", params.ID)
@ -49,7 +49,7 @@ func Host(mctx helpers.MetricsCtx, lc fx.Lifecycle, params P2PHostIn) (RawHost,
libp2p.Peerstore(params.Peerstore), libp2p.Peerstore(params.Peerstore),
libp2p.NoListenAddrs, libp2p.NoListenAddrs,
libp2p.Ping(true), libp2p.Ping(true),
libp2p.UserAgent("lotus-" + build.UserVersion()), libp2p.UserAgent("lotus-" + string(buildVersion)),
} }
for _, o := range params.Opts { for _, o := range params.Opts {
opts = append(opts, o...) opts = append(opts, o...)