@@ -4,11 +4,13 @@ import (
44 "context"
55 "fmt"
66 "os"
7+ "path/filepath"
78
89 "github.com/localstack/lstk/internal/api"
910 "github.com/localstack/lstk/internal/config"
1011 "github.com/localstack/lstk/internal/container"
1112 "github.com/localstack/lstk/internal/env"
13+ "github.com/localstack/lstk/internal/log"
1214 "github.com/localstack/lstk/internal/output"
1315 "github.com/localstack/lstk/internal/runtime"
1416 "github.com/localstack/lstk/internal/telemetry"
@@ -17,7 +19,7 @@ import (
1719 "github.com/spf13/cobra"
1820)
1921
20- func NewRootCmd (cfg * env.Env , tel * telemetry.Client ) * cobra.Command {
22+ func NewRootCmd (cfg * env.Env , tel * telemetry.Client , logger log. Logger ) * cobra.Command {
2123 root := & cobra.Command {
2224 Use : "lstk" ,
2325 Short : "LocalStack CLI" ,
@@ -28,7 +30,7 @@ func NewRootCmd(cfg *env.Env, tel *telemetry.Client) *cobra.Command {
2830 if err != nil {
2931 return err
3032 }
31- return runStart (cmd .Context (), rt , cfg , tel )
33+ return runStart (cmd .Context (), rt , cfg , tel , logger )
3234 },
3335 }
3436
@@ -46,10 +48,10 @@ func NewRootCmd(cfg *env.Env, tel *telemetry.Client) *cobra.Command {
4648 root .Flags ().Lookup ("version" ).Usage = "Show version"
4749
4850 root .AddCommand (
49- newStartCmd (cfg , tel ),
51+ newStartCmd (cfg , tel , logger ),
5052 newStopCmd (cfg ),
51- newLoginCmd (cfg ),
52- newLogoutCmd (cfg ),
53+ newLoginCmd (cfg , logger ),
54+ newLogoutCmd (cfg , logger ),
5355 newLogsCmd (),
5456 newConfigCmd (),
5557 newVersionCmd (),
@@ -64,7 +66,10 @@ func Execute(ctx context.Context) error {
6466 tel := telemetry .New (cfg .AnalyticsEndpoint , cfg .DisableEvents )
6567 defer tel .Close ()
6668
67- root := NewRootCmd (cfg , tel )
69+ logger , cleanup := newLogger ()
70+ defer cleanup ()
71+
72+ root := NewRootCmd (cfg , tel , logger )
6873 root .SilenceErrors = true
6974 root .SilenceUsage = true
7075
@@ -77,7 +82,7 @@ func Execute(ctx context.Context) error {
7782 return nil
7883}
7984
80- func runStart (ctx context.Context , rt runtime.Runtime , cfg * env.Env , tel * telemetry.Client ) error {
85+ func runStart (ctx context.Context , rt runtime.Runtime , cfg * env.Env , tel * telemetry.Client , logger log. Logger ) error {
8186 // TODO: replace map with a typed payload struct once event schema is finalised
8287 tel .Emit (ctx , "cli_cmd" , map [string ]any {"cmd" : "lstk start" , "params" : []string {}})
8388
@@ -94,7 +99,9 @@ func runStart(ctx context.Context, rt runtime.Runtime, cfg *env.Env, tel *teleme
9499 LocalStackHost : cfg .LocalStackHost ,
95100 Containers : appConfig .Containers ,
96101 Env : appConfig .Env ,
102+ Logger : logger ,
97103 }
104+
98105 if isInteractiveMode (cfg ) {
99106 return ui .Run (ctx , rt , version .Version (), opts )
100107 }
@@ -105,6 +112,24 @@ func isInteractiveMode(cfg *env.Env) bool {
105112 return ! cfg .NonInteractive && ui .IsInteractive ()
106113}
107114
115+ const maxLogSize = 1 << 20 // 1 MB
116+
117+ func newLogger () (log.Logger , func ()) {
118+ configDir , err := config .ConfigDir ()
119+ if err != nil {
120+ return log .Nop (), func () {}
121+ }
122+ path := filepath .Join (configDir , "lstk.log" )
123+ if info , err := os .Stat (path ); err == nil && info .Size () > maxLogSize {
124+ _ = os .Truncate (path , 0 )
125+ }
126+ f , err := os .OpenFile (path , os .O_APPEND | os .O_CREATE | os .O_WRONLY , 0644 )
127+ if err != nil {
128+ return log .Nop (), func () {}
129+ }
130+ return log .New (f ), func () { _ = f .Close () }
131+ }
132+
108133func initConfig (cmd * cobra.Command , _ []string ) error {
109134 path , err := cmd .Flags ().GetString ("config" )
110135 if err != nil {
0 commit comments