@@ -5,19 +5,24 @@ import (
55 _ "embed"
66 "fmt"
77 "log"
8+ "log/slog"
89 "os"
910 "sort"
1011 "strings"
1112 "time"
1213
14+ "github.com/fatih/color"
1315 "github.com/flashbots/builder-playground/playground"
1416 "github.com/flashbots/builder-playground/utils"
17+ "github.com/flashbots/builder-playground/utils/logging"
1518 "github.com/flashbots/builder-playground/utils/mainctx"
1619 "github.com/spf13/cobra"
1720)
1821
1922var version = "dev"
2023
24+ var greenColor = color .New (color .FgGreen )
25+
2126var (
2227 keepFlag bool
2328 outputFlag string
@@ -315,17 +320,17 @@ func main() {
315320}
316321
317322func runIt (recipe playground.Recipe ) error {
323+ fmt .Println ()
324+
318325 var logLevel playground.LogLevel
319326 if err := logLevel .Unmarshal (logLevelFlag ); err != nil {
320327 return fmt .Errorf ("failed to parse log level: %w" , err )
321328 }
322-
323- if logLevel == playground .LevelTrace {
324- // TODO: We can remove this once we have a logger with log.Trace support
325- utils .TraceMode = true
326- }
327-
328- log .Printf ("Log level: %s\n " , logLevel )
329+ logging .ConfigureSlog (logLevelFlag )
330+ sessionID := utils .GeneratePetName ()
331+ slog .Info ("Welcome to Builder Playground! ⚡️🤖" )
332+ slog .Info ("Session ID: " + greenColor .Sprint (sessionID ), "log-level" , logLevel )
333+ slog .Info ("" )
329334
330335 // parse the overrides
331336 overrides := map [string ]string {}
@@ -342,7 +347,7 @@ func runIt(recipe playground.Recipe) error {
342347 return err
343348 }
344349
345- log . Println ("Building artifacts..." )
350+ slog . Debug ("Building artifacts..." )
346351 builder := recipe .Artifacts ()
347352 builder .GenesisDelay (genesisDelayFlag )
348353 builder .PrefundedAccounts (prefundedAccounts )
@@ -360,12 +365,12 @@ func runIt(recipe playground.Recipe) error {
360365 },
361366 }
362367
363- svcManager := playground .NewManifest (exCtx , out )
368+ svcManager := playground .NewManifest (exCtx , out , sessionID )
364369
365370 recipe .Apply (svcManager )
366371
367372 // generate the dot graph
368- log . Println ("Generating dot graph..." )
373+ slog . Debug ("Generating dot graph..." )
369374 dotGraph := svcManager .GenerateDotGraph ()
370375 if err := out .WriteFile ("graph.dot" , dotGraph ); err != nil {
371376 return err
@@ -410,11 +415,9 @@ func runIt(recipe playground.Recipe) error {
410415 }
411416
412417 // Add callback to log service updates in debug mode
413- if logLevel == playground .LevelDebug {
414- cfg .AddCallback (func (serviceName string , update playground.TaskStatus ) {
415- log .Printf ("[DEBUG] [%s] %s\n " , serviceName , update )
416- })
417- }
418+ cfg .AddCallback (func (serviceName string , update playground.TaskStatus ) {
419+ slog .Debug ("service update" , "service" , serviceName , "status" , update )
420+ })
418421
419422 dockerRunner , err := playground .NewLocalRunner (cfg )
420423 if err != nil {
@@ -423,50 +426,53 @@ func runIt(recipe playground.Recipe) error {
423426
424427 ctx := mainctx .Get ()
425428
426- log . Println ("Starting services..." )
429+ slog . Info ("Starting services... ⏳" , "session-id" , svcManager . ID )
427430 if err := dockerRunner .Run (ctx ); err != nil {
428431 dockerRunner .Stop (keepFlag )
429432 return fmt .Errorf ("failed to run docker: %w" , err )
430433 }
431434
432435 if ! interactive {
436+ log .Println ()
437+ log .Println ("All services started! ✅" )
433438 // print services info
434- fmt .Printf ("\n ========= Services started =========\n " )
435439 for _ , ss := range svcManager .Services {
436440 ports := ss .GetPorts ()
437441 sort .Slice (ports , func (i , j int ) bool {
438442 return ports [i ].Name < ports [j ].Name
439443 })
440444
441- portsStr := [] string {}
445+ var portsStr [] any
442446 for _ , p := range ports {
443447 protocol := ""
444448 if p .Protocol == playground .ProtocolUDP {
445449 protocol = "/udp"
446450 }
447- portsStr = append (portsStr , fmt .Sprintf ("%s: % d/%d%s" , p . Name , p .Port , p .HostPort , protocol ))
451+ portsStr = append (portsStr , p . Name , fmt .Sprintf ("%d/%d%s" , p .Port , p .HostPort , protocol ))
448452 }
449- fmt . Printf ( "- %s (%s) \n " , ss .Name , strings . Join ( portsStr , ", " ) )
453+ slog . Info ( "• " + ss .Name , portsStr ... )
450454 }
455+ log .Println ()
451456 }
452457
453- fmt .Println ("\n Waiting for services to get healthy..." )
458+ log .Println ("Waiting for services to get healthy... ⏳ " )
454459 waitCtx , cancel := context .WithTimeout (ctx , time .Minute )
455460 defer cancel ()
456461 if err := dockerRunner .WaitForReady (waitCtx ); err != nil {
457462 dockerRunner .Stop (keepFlag )
458463 return fmt .Errorf ("failed to wait for service readiness: %w" , err )
459464 }
460465
461- fmt .Println ("\n All services are healthy! Ready to accept transactions." )
462- fmt .Println ("Session ID:" , svcManager .ID )
466+ slog .Info ("All services are healthy! Ready to accept transactions. 🚀" , "session-id" , svcManager .ID )
463467
464468 // get the output from the recipe
465469 output := recipe .Output (svcManager )
466470 if len (output ) > 0 {
467- fmt .Printf ("\n ========= Output =========\n " )
471+ slog .Info ("" )
472+ slog .Info ("Recipe outputs 🔍" )
468473 for k , v := range output {
469- fmt .Printf ("- %s: %v\n " , k , v )
474+ valStr := fmt .Sprintf ("%v" , v )
475+ slog .Info ("• " + k + ": " + greenColor .Sprint (valStr ))
470476 }
471477 }
472478
@@ -492,13 +498,13 @@ func runIt(recipe playground.Recipe) error {
492498
493499 select {
494500 case <- ctx .Done ():
495- fmt .Println ("Stopping..." )
501+ log .Println ("Stopping..." )
496502 case err := <- dockerRunner .ExitErr ():
497- fmt .Println ("Service failed:" , err )
503+ log .Println ("Service failed:" , err )
498504 case err := <- watchdogErr :
499- fmt .Println ("Watchdog failed:" , err )
505+ log .Println ("Watchdog failed:" , err )
500506 case <- timerCh :
501- fmt .Println ("Timeout reached" )
507+ log .Println ("Timeout reached" )
502508 }
503509
504510 if err := dockerRunner .Stop (keepFlag ); err != nil {
0 commit comments