Skip to content

Commit 3977b22

Browse files
authored
feat: create post action runapp step and emit app logs to ~/.minitia/app.log (#161)
* create post action runapp step and emit app logs to ~/.minitia/app.log * use type * nil safety
1 parent d36a0a1 commit 3977b22

4 files changed

Lines changed: 96 additions & 61 deletions

File tree

contrib/launchtools/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ $ launchtools launch --artifacts-dir ./ --with-config ./config.json
7373
defaultGenesisGetter(config.L2Config.Denom),
7474
artifactsDir,
7575
)
76+
defer launcher.Close()
7677

7778
stepFns := make([]LauncherStepFunc, len(steps))
7879

contrib/launchtools/steps/ibc.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ func establishIBCChannels(
7171

7272
relayer := NewRelayer(ctx.Context(), relayerPath, ctx.Logger())
7373
ctx.SetRelayer(relayer)
74-
7574
return runLifecycle(relayer)
7675
}
7776
}

contrib/launchtools/steps/runapp.go

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,81 +4,95 @@ import (
44
"context"
55
"time"
66

7+
"github.com/pkg/errors"
8+
"golang.org/x/sync/errgroup"
9+
710
"github.com/cosmos/cosmos-sdk/client"
811
"github.com/cosmos/cosmos-sdk/server"
12+
913
"github.com/initia-labs/OPinit/contrib/launchtools"
10-
"github.com/pkg/errors"
11-
"golang.org/x/sync/errgroup"
1214
)
1315

1416
var _ launchtools.LauncherStepFuncFactory[*launchtools.Config] = RunApp
1517

1618
// RunApp runs the in-process application. This routine temporarily allows creation of empty blocks,
1719
// in order to expedite IBC channel establishment. It waits until the app generates at least 1 block after the genesis.
18-
func RunApp(_ *launchtools.Config) launchtools.LauncherStepFunc {
19-
return func(ctx launchtools.Launcher) error {
20-
// temporarily allow creation of empty blocks
21-
// this should help creation of ibc channels.
22-
// NOTE: This part is ephemeral only in the context of the launcher.
23-
ctx.ServerContext().Config.Consensus.CreateEmptyBlocks = true
24-
ctx.ServerContext().Config.Consensus.CreateEmptyBlocksInterval = CreateEmptyBlocksInterval
25-
26-
// create a channel to synchronize on app creation
27-
var syncDone = make(chan interface{})
28-
29-
// create cobra command context
30-
startCmd := server.StartCmdWithOptions(
31-
ctx.AppCreator(),
32-
ctx.ClientContext().HomeDir,
33-
34-
// set up a post setup function to set the app in the context
35-
server.StartCmdOptions{
36-
PostSetup: func(svrCtx *server.Context, clientCtx client.Context, _ context.Context, g *errgroup.Group) (err error) {
37-
// set the error group to gracefully shutdown the launch cmd
38-
ctx.SetErrorGroup(g)
39-
40-
// wait until latest version goes to 2
41-
g.Go(func() error {
42-
for {
43-
ctx.Logger().Info("waiting for app to be created")
44-
45-
if ctx.App().CommitMultiStore().LatestVersion() > 1 {
46-
// Signal that the app is created
47-
syncDone <- struct{}{}
48-
break
20+
func RunApp(cfg *launchtools.Config) launchtools.LauncherStepFunc {
21+
return RunAppWithPostAction(nil)(cfg)
22+
}
23+
24+
// RunAppWithPostAction runs the in-process application with a post action.
25+
func RunAppWithPostAction(postAction launchtools.PostAction) func(cfg *launchtools.Config) launchtools.LauncherStepFunc {
26+
return func(cfg *launchtools.Config) launchtools.LauncherStepFunc {
27+
return func(ctx launchtools.Launcher) error {
28+
// temporarily allow creation of empty blocks
29+
// this should help creation of ibc channels.
30+
// NOTE: This part is ephemeral only in the context of the launcher.
31+
ctx.ServerContext().Config.Consensus.CreateEmptyBlocks = true
32+
ctx.ServerContext().Config.Consensus.CreateEmptyBlocksInterval = CreateEmptyBlocksInterval
33+
34+
// create a channel to synchronize on app creation
35+
var syncDone = make(chan interface{})
36+
37+
// create cobra command context
38+
startCmd := server.StartCmdWithOptions(
39+
ctx.AppCreator(),
40+
ctx.ClientContext().HomeDir,
41+
42+
// set up a post setup function to set the app in the context
43+
server.StartCmdOptions{
44+
PostSetup: func(svrCtx *server.Context, clientCtx client.Context, _ctx context.Context, g *errgroup.Group) (err error) {
45+
// set the error group to gracefully shutdown the launch cmd
46+
ctx.SetErrorGroup(g)
47+
48+
// wait until latest version goes to 2
49+
g.Go(func() error {
50+
for {
51+
ctx.Logger().Info("waiting for app to be created")
52+
53+
if ctx.App().CommitMultiStore().LatestVersion() > 1 {
54+
// Signal that the app is created
55+
syncDone <- struct{}{}
56+
break
57+
}
58+
59+
time.Sleep(1 * time.Second)
4960
}
5061

51-
time.Sleep(1 * time.Second)
62+
return nil
63+
})
64+
65+
// if post action is set, run it
66+
if postAction != nil {
67+
return postAction(ctx.App(), svrCtx, clientCtx, _ctx, g)
5268
}
5369

5470
return nil
55-
})
56-
57-
return nil
71+
},
5872
},
59-
},
60-
)
73+
)
6174

62-
// set relevant context; this part is necessary to correctly set up the start command and their start-up flags
63-
startCmd.SetContext(ctx.Context())
75+
// set relevant context; this part is necessary to correctly set up the start command and their start-up flags
76+
startCmd.SetContext(ctx.Context())
6477

65-
// Run PreRunE from startCmd. This step is necessary to correctly set up start-up flags,
66-
// as it is done usually with cometbft start command.
67-
if err := startCmd.PreRunE(startCmd, nil); err != nil {
68-
return errors.Wrapf(err, "failed to prerun command")
69-
}
70-
71-
// Run RunE command - this part fires up the actual chain
72-
// Note that the command is run in a separate goroutine, as it is blocking.
73-
// App should be later cleaned up in another launcher step
74-
go func() {
75-
if err := startCmd.RunE(startCmd, nil); err != nil {
76-
panic(errors.Wrapf(err, "failed to run command"))
78+
// Run PreRunE from startCmd. This step is necessary to correctly set up start-up flags,
79+
// as it is done usually with cometbft start command.
80+
if err := startCmd.PreRunE(startCmd, nil); err != nil {
81+
return errors.Wrapf(err, "failed to prerun command")
7782
}
78-
}()
7983

80-
<-syncDone
84+
// Run RunE command - this part fires up the actual chain
85+
// Note that the command is run in a separate goroutine, as it is blocking.
86+
// App should be later cleaned up in another launcher step
87+
go func() {
88+
if err := startCmd.RunE(startCmd, nil); err != nil {
89+
panic(errors.Wrapf(err, "failed to run command"))
90+
}
91+
}()
92+
93+
<-syncDone
8194

82-
return nil
95+
return nil
96+
}
8397
}
8498
}

contrib/launchtools/types.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ type ExpectedApp interface {
4343
GetIBCKeeper() *ibckeeper.Keeper
4444
}
4545

46+
// PostAction is a function that is called after the app is created.
47+
type PostAction func(app ExpectedApp, svrCtx *server.Context, clientCtx client.Context, ctx context.Context, g *errgroup.Group) error
48+
4649
type AppCreator interface {
4750
AppCreator() servertypes.AppCreator
4851
App() servertypes.Application
@@ -112,7 +115,8 @@ type Launcher interface {
112115
var _ Launcher = &LauncherContext{}
113116

114117
type LauncherContext struct {
115-
mtx *sync.Mutex
118+
mtx *sync.Mutex
119+
appLogFile *os.File
116120

117121
log log.Logger
118122
defaultGenesis map[string]json.RawMessage
@@ -154,8 +158,14 @@ func NewLauncher(
154158
// create a new client context with the keyring
155159
nextClientCtx := clientCtx.WithKeyring(kr)
156160

157-
// mute log output
158-
serverCtx.Logger = log.NewNopLogger()
161+
// record app logs to file
162+
appLogFile, err := os.Create(path.Join(nextClientCtx.HomeDir, "app.log"))
163+
if err != nil {
164+
panic("failed to create log file")
165+
}
166+
167+
serverCtx.Logger.Info("logging app logs to file", "file", appLogFile.Name())
168+
serverCtx.Logger = log.NewLogger(appLogFile, log.OutputJSONOption())
159169

160170
// make sure to register both ophost and opchild proto
161171
// otherwise it fails on creating op bridge on L1
@@ -169,8 +179,9 @@ func NewLauncher(
169179
}
170180

171181
return &LauncherContext{
172-
log: log.NewLogger(os.Stderr),
173182
mtx: new(sync.Mutex),
183+
appLogFile: appLogFile,
184+
log: log.NewLogger(os.Stderr),
174185
clientCtx: &nextClientCtx,
175186
serverCtx: serverCtx,
176187
appCreator: appCreator,
@@ -290,3 +301,13 @@ func (l *LauncherContext) SetErrorGroup(g *errgroup.Group) {
290301
func (l *LauncherContext) GetErrorGroup() *errgroup.Group {
291302
return l.errorgroup
292303
}
304+
305+
func (l *LauncherContext) Close() error {
306+
if l.appLogFile != nil {
307+
if err := l.appLogFile.Close(); err != nil {
308+
return errors.Wrap(err, "failed to close app log file")
309+
}
310+
}
311+
312+
return nil
313+
}

0 commit comments

Comments
 (0)