mirror of https://github.com/gofiber/fiber.git
✨ v3: Change startup message (#2041)
* Add figlet text for Fiber startup message * Fiber figlet text is added to beginning of the startup message. Signed-off-by: Gökhan Özeloğlu <gokhan.ozeloglu@deliveryhero.com> * Refactor startup message * Table is removed. Logs are added. * Test cases refactored. Signed-off-by: Gökhan Özeloğlu <gokhan.ozeloglu@deliveryhero.com> * Add colorful log messages * Used custom color codes to make logs colorful. * Added a new test case. * Fixed broken test case after changes. * Added some color codes as a variable. * Handled Windows case with init() function. Color codes are set empty string. Signed-off-by: Gökhan Özeloğlu <gokhan.ozeloglu@deliveryhero.com> * Change color text logic * Color codes are taken from config. * Version is added to figlet text. * Reordered "server started on" message. * Test cases are refactored. Signed-off-by: Gökhan Özeloğlu <gokhan.ozeloglu@deliveryhero.com> * Add if condition for Windows * OS checked in tests for Windows machines. Signed-off-by: Gökhan Özeloğlu <gokhan.ozeloglu@deliveryhero.com> * some improvements * Fix startup message tests Signed-off-by: Gökhan Özeloğlu <gokhan.ozeloglu@deliveryhero.com> * colorize PIDs Signed-off-by: Gökhan Özeloğlu <gokhan.ozeloglu@deliveryhero.com> Co-authored-by: Muhammed Efe Çetin <efectn@protonmail.com>pull/2130/head
parent
281e2f0046
commit
1a7f7ed8a9
189
listen.go
189
listen.go
|
@ -24,6 +24,14 @@ import (
|
|||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
// Figlet text to show Fiber ASCII art on startup message
|
||||
var figletFiberText = `
|
||||
_______ __
|
||||
/ ____(_) /_ ___ _____
|
||||
/ /_ / / __ \/ _ \/ ___/
|
||||
/ __/ / / /_/ / __/ /
|
||||
/_/ /_/_.___/\___/_/ %s`
|
||||
|
||||
// ListenConfig is a struct to customize startup of Fiber.
|
||||
//
|
||||
// TODO: Add timeout for graceful shutdown.
|
||||
|
@ -279,52 +287,6 @@ func (app *App) startupMessage(addr string, tls bool, pids string, cfg ListenCon
|
|||
// Alias colors
|
||||
colors := app.config.ColorScheme
|
||||
|
||||
value := func(s string, width int) string {
|
||||
pad := width - len(s)
|
||||
str := ""
|
||||
for i := 0; i < pad; i++ {
|
||||
str += "."
|
||||
}
|
||||
if s == "Disabled" {
|
||||
str += " " + s
|
||||
} else {
|
||||
str += fmt.Sprintf(" %s%s%s", colors.Cyan, s, colors.Black)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
center := func(s string, width int) string {
|
||||
pad := strconv.Itoa((width - len(s)) / 2)
|
||||
str := fmt.Sprintf("%"+pad+"s", " ")
|
||||
str += s
|
||||
str += fmt.Sprintf("%"+pad+"s", " ")
|
||||
if len(str) < width {
|
||||
str += " "
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
centerValue := func(s string, width int) string {
|
||||
pad := strconv.Itoa((width - len([]rune(s))) / 2)
|
||||
str := fmt.Sprintf("%"+pad+"s", " ")
|
||||
str += fmt.Sprintf("%s%s%s", colors.Cyan, s, colors.Black)
|
||||
str += fmt.Sprintf("%"+pad+"s", " ")
|
||||
if len([]rune(s))-10 < width && len([]rune(s))%2 == 0 {
|
||||
// add an ending space if the length of str is even and str is not too long
|
||||
str += " "
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
pad := func(s string, width int) (str string) {
|
||||
toAdd := width - len(s)
|
||||
str += s
|
||||
for i := 0; i < toAdd; i++ {
|
||||
str += " "
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
host, port := parseAddr(addr)
|
||||
if host == "" {
|
||||
if cfg.ListenerNetwork == NetworkTCP6 {
|
||||
|
@ -349,41 +311,39 @@ func (app *App) startupMessage(addr string, tls bool, pids string, cfg ListenCon
|
|||
procs = "1"
|
||||
}
|
||||
|
||||
mainLogo := colors.Black + " ┌───────────────────────────────────────────────────┐\n"
|
||||
if app.config.AppName != "" {
|
||||
mainLogo += " │ " + centerValue(app.config.AppName, 49) + " │\n"
|
||||
out := colorable.NewColorableStdout()
|
||||
if os.Getenv("TERM") == "dumb" || os.Getenv("NO_COLOR") == "1" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) {
|
||||
out = colorable.NewNonColorable(os.Stdout)
|
||||
}
|
||||
mainLogo += " │ " + centerValue("Fiber v"+Version, 49) + " │\n"
|
||||
|
||||
_, _ = fmt.Fprintf(out, "%s\n", fmt.Sprintf(figletFiberText, colors.Red+"v"+Version+colors.Reset))
|
||||
_, _ = fmt.Fprintf(out, strings.Repeat("-", 50)+"\n")
|
||||
|
||||
if host == "0.0.0.0" {
|
||||
mainLogo +=
|
||||
" │ " + center(fmt.Sprintf("%s://127.0.0.1:%s", scheme, port), 49) + " │\n" +
|
||||
" │ " + center(fmt.Sprintf("(bound on host 0.0.0.0 and port %s)", port), 49) + " │\n"
|
||||
_, _ = fmt.Fprintf(out,
|
||||
"%sINFO%s Server started on %s%s://127.0.0.1:%s%s (bound on host 0.0.0.0 and port %s)\n",
|
||||
colors.Green, colors.Reset, colors.Blue, scheme, port, colors.Reset, port)
|
||||
} else {
|
||||
mainLogo +=
|
||||
" │ " + center(fmt.Sprintf("%s://%s:%s", scheme, host, port), 49) + " │\n"
|
||||
_, _ = fmt.Fprintf(out,
|
||||
"%sINFO%s Server started on %s%s%s\n",
|
||||
colors.Green, colors.Reset, colors.Blue, fmt.Sprintf("%s://%s:%s", scheme, host, port), colors.Reset)
|
||||
}
|
||||
|
||||
mainLogo += fmt.Sprintf(
|
||||
" │ │\n"+
|
||||
" │ Handlers %s Processes %s │\n"+
|
||||
" │ Prefork .%s PID ....%s │\n"+
|
||||
" └───────────────────────────────────────────────────┘"+
|
||||
colors.Reset,
|
||||
value(strconv.Itoa(int(app.handlersCount)), 14), value(procs, 12),
|
||||
value(isPrefork, 14), value(strconv.Itoa(os.Getpid()), 14),
|
||||
)
|
||||
if app.config.AppName != "" {
|
||||
_, _ = fmt.Fprintf(out, "%sINFO%s Application name: %s%s%s\n", colors.Green, colors.Reset, colors.Blue, app.config.AppName, colors.Reset)
|
||||
}
|
||||
_, _ = fmt.Fprintf(out,
|
||||
"%sINFO%s Total handlers count: %s%s%s\n",
|
||||
colors.Green, colors.Reset, colors.Blue, strconv.Itoa(int(app.handlersCount)), colors.Reset)
|
||||
if isPrefork == "Enabled" {
|
||||
_, _ = fmt.Fprintf(out, "%sINFO%s Prefork: %s%s%s\n", colors.Green, colors.Reset, colors.Blue, isPrefork, colors.Reset)
|
||||
} else {
|
||||
_, _ = fmt.Fprintf(out, "%sINFO%s Prefork: %s%s%s\n", colors.Green, colors.Reset, colors.Red, isPrefork, colors.Reset)
|
||||
}
|
||||
_, _ = fmt.Fprintf(out, "%sINFO%s PID: %s%v%s\n", colors.Green, colors.Reset, colors.Blue, os.Getpid(), colors.Reset)
|
||||
_, _ = fmt.Fprintf(out, "%sINFO%s Total process count: %s%s%s\n", colors.Green, colors.Reset, colors.Blue, procs, colors.Reset)
|
||||
|
||||
var childPidsLogo string
|
||||
if cfg.EnablePrefork {
|
||||
var childPidsTemplate string
|
||||
childPidsTemplate += "%s"
|
||||
childPidsTemplate += " ┌───────────────────────────────────────────────────┐\n%s"
|
||||
childPidsTemplate += " └───────────────────────────────────────────────────┘"
|
||||
childPidsTemplate += "%s"
|
||||
|
||||
newLine := " │ %s%s%s │"
|
||||
|
||||
// Turn the `pids` variable (in the form ",a,b,c,d,e,f,etc") into a slice of PIDs
|
||||
var pidSlice []string
|
||||
for _, v := range strings.Split(pids, ",") {
|
||||
|
@ -392,77 +352,24 @@ func (app *App) startupMessage(addr string, tls bool, pids string, cfg ListenCon
|
|||
}
|
||||
}
|
||||
|
||||
var lines []string
|
||||
thisLine := "Child PIDs ... "
|
||||
var itemsOnThisLine []string
|
||||
|
||||
addLine := func() {
|
||||
lines = append(lines,
|
||||
fmt.Sprintf(
|
||||
newLine,
|
||||
colors.Black,
|
||||
thisLine+colors.Cyan+pad(strings.Join(itemsOnThisLine, ", "), 49-len(thisLine)),
|
||||
colors.Black,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
for _, pid := range pidSlice {
|
||||
if len(thisLine+strings.Join(append(itemsOnThisLine, pid), ", ")) > 49 {
|
||||
addLine()
|
||||
thisLine = ""
|
||||
itemsOnThisLine = []string{pid}
|
||||
} else {
|
||||
itemsOnThisLine = append(itemsOnThisLine, pid)
|
||||
_, _ = fmt.Fprintf(out, "%sINFO%s Child PIDs: %s", colors.Green, colors.Reset, colors.Blue)
|
||||
totalPids := len(pidSlice)
|
||||
rowTotalPidCount := 10
|
||||
for i := 0; i < totalPids; i += rowTotalPidCount {
|
||||
start := i
|
||||
end := i + rowTotalPidCount
|
||||
if end > totalPids {
|
||||
end = totalPids
|
||||
}
|
||||
}
|
||||
|
||||
// Add left over items to their own line
|
||||
if len(itemsOnThisLine) != 0 {
|
||||
addLine()
|
||||
}
|
||||
|
||||
// Form logo
|
||||
childPidsLogo = fmt.Sprintf(childPidsTemplate,
|
||||
colors.Black,
|
||||
strings.Join(lines, "\n")+"\n",
|
||||
colors.Reset,
|
||||
)
|
||||
}
|
||||
|
||||
// Combine both the child PID logo and the main Fiber logo
|
||||
|
||||
// Pad the shorter logo to the length of the longer one
|
||||
splitMainLogo := strings.Split(mainLogo, "\n")
|
||||
splitChildPidsLogo := strings.Split(childPidsLogo, "\n")
|
||||
|
||||
mainLen := len(splitMainLogo)
|
||||
childLen := len(splitChildPidsLogo)
|
||||
|
||||
if mainLen > childLen {
|
||||
diff := mainLen - childLen
|
||||
for i := 0; i < diff; i++ {
|
||||
splitChildPidsLogo = append(splitChildPidsLogo, "")
|
||||
}
|
||||
} else {
|
||||
diff := childLen - mainLen
|
||||
for i := 0; i < diff; i++ {
|
||||
splitMainLogo = append(splitMainLogo, "")
|
||||
for n, pid := range pidSlice[start:end] {
|
||||
_, _ = fmt.Fprintf(out, "%s", pid)
|
||||
if n+1 != len(pidSlice[start:end]) {
|
||||
_, _ = fmt.Fprintf(out, ", ")
|
||||
}
|
||||
}
|
||||
_, _ = fmt.Fprintf(out, "\n%s", colors.Reset)
|
||||
}
|
||||
}
|
||||
|
||||
// Combine the two logos, line by line
|
||||
output := "\n"
|
||||
for i := range splitMainLogo {
|
||||
output += colors.Black + splitMainLogo[i] + " " + splitChildPidsLogo[i] + "\n"
|
||||
}
|
||||
|
||||
out := colorable.NewColorableStdout()
|
||||
if os.Getenv("TERM") == "dumb" || os.Getenv("NO_COLOR") == "1" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) {
|
||||
out = colorable.NewNonColorable(os.Stdout)
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintln(out, output)
|
||||
}
|
||||
|
||||
// printRoutesMessage print all routes with method, path, name and handlers
|
||||
|
|
|
@ -349,12 +349,13 @@ func Test_Listen_Master_Process_Show_Startup_Message(t *testing.T) {
|
|||
New().
|
||||
startupMessage(":3000", true, strings.Repeat(",11111,22222,33333,44444,55555,60000", 10), cfg)
|
||||
})
|
||||
colors := Colors{}
|
||||
fmt.Println(startupMessage)
|
||||
require.True(t, strings.Contains(startupMessage, "https://127.0.0.1:3000"))
|
||||
require.True(t, strings.Contains(startupMessage, "(bound on host 0.0.0.0 and port 3000)"))
|
||||
require.True(t, strings.Contains(startupMessage, "Child PIDs"))
|
||||
require.True(t, strings.Contains(startupMessage, "11111, 22222, 33333, 44444, 55555, 60000"))
|
||||
require.True(t, strings.Contains(startupMessage, "Prefork ........ Enabled"))
|
||||
require.True(t, strings.Contains(startupMessage, fmt.Sprintf("Prefork: %sEnabled%s", colors.Blue, colors.Reset)))
|
||||
}
|
||||
|
||||
// go test -run Test_Listen_Master_Process_Show_Startup_MessageWithAppName
|
||||
|
@ -372,17 +373,49 @@ func Test_Listen_Master_Process_Show_Startup_MessageWithAppName(t *testing.T) {
|
|||
require.True(t, strings.Contains(startupMessage, app.Config().AppName))
|
||||
}
|
||||
|
||||
// go test -run Test_Listen_Master_Process_Show_Startup_MessageWithAppNameNonAscii
|
||||
func Test_Listen_Master_Process_Show_Startup_MessageWithAppNameNonAscii(t *testing.T) {
|
||||
cfg := ListenConfig{
|
||||
EnablePrefork: true,
|
||||
}
|
||||
|
||||
appName := "Serveur de vérification des données"
|
||||
app := New(Config{AppName: appName})
|
||||
|
||||
startupMessage := captureOutput(func() {
|
||||
app.startupMessage(":3000", false, "", cfg)
|
||||
})
|
||||
fmt.Println(startupMessage)
|
||||
require.True(t, strings.Contains(startupMessage, "Serveur de vérification des données"))
|
||||
}
|
||||
|
||||
// go test -run Test_Listen_Master_Process_Show_Startup_MessageWithDisabledPreforkAndCustomEndpoint
|
||||
func Test_Listen_Master_Process_Show_Startup_MessageWithDisabledPreforkAndCustomEndpoint(t *testing.T) {
|
||||
cfg := ListenConfig{
|
||||
EnablePrefork: false,
|
||||
}
|
||||
|
||||
appName := "Fiber Example Application"
|
||||
app := New(Config{AppName: appName})
|
||||
startupMessage := captureOutput(func() {
|
||||
app.startupMessage("server.com:8081", true, strings.Repeat(",11111,22222,33333,44444,55555,60000", 5), cfg)
|
||||
})
|
||||
colors := Colors{}
|
||||
fmt.Println(startupMessage)
|
||||
require.True(t, strings.Contains(startupMessage, fmt.Sprintf("%sINFO%s", colors.Green, colors.Reset)))
|
||||
require.True(t, strings.Contains(startupMessage, fmt.Sprintf("%s%s%s", colors.Blue, appName, colors.Reset)))
|
||||
require.True(t, strings.Contains(startupMessage, fmt.Sprintf("%s%s%s", colors.Blue, "https://server.com:8081", colors.Reset)))
|
||||
require.True(t, strings.Contains(startupMessage, fmt.Sprintf("Prefork: %sDisabled%s", colors.Red, colors.Reset)))
|
||||
}
|
||||
|
||||
// go test -run Test_Listen_Print_Route
|
||||
func Test_Listen_Print_Route(t *testing.T) {
|
||||
app := New()
|
||||
app.Get("/", emptyHandler).Name("routeName")
|
||||
|
||||
printRoutesMessage := captureOutput(func() {
|
||||
app.printRoutesMessage()
|
||||
})
|
||||
|
||||
fmt.Println(printRoutesMessage)
|
||||
|
||||
require.True(t, strings.Contains(printRoutesMessage, "GET"))
|
||||
require.True(t, strings.Contains(printRoutesMessage, "/"))
|
||||
require.True(t, strings.Contains(printRoutesMessage, "emptyHandler"))
|
||||
|
@ -403,8 +436,6 @@ func Test_Listen_Print_Route_With_Group(t *testing.T) {
|
|||
app.printRoutesMessage()
|
||||
})
|
||||
|
||||
fmt.Println(printRoutesMessage)
|
||||
|
||||
require.True(t, strings.Contains(printRoutesMessage, "GET"))
|
||||
require.True(t, strings.Contains(printRoutesMessage, "/"))
|
||||
require.True(t, strings.Contains(printRoutesMessage, "emptyHandler"))
|
||||
|
|
Loading…
Reference in New Issue