chore: reduce log volume on server startup (#16608)

Addresses https://github.com/coder/coder/issues/16231.

This PR reduces the volume of logs we print after server startup in
order to surface the web UI URL better.

Here are the logs after the changes a couple of seconds after starting
the server:

<img width="868" alt="Screenshot 2025-02-18 at 16 31 32"
src="https://github.com/user-attachments/assets/786dc4b8-7383-48c8-a5c3-a997c01ca915"
/>

The warning is due to running a development site-less build. It wouldn't
show in a release build.
This commit is contained in:
Hugo Dutka
2025-02-20 16:33:14 +01:00
committed by GitHub
parent 54b09d9878
commit 44499315ed
12 changed files with 207 additions and 61 deletions

View File

@ -25,6 +25,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"testing"
"time"
@ -240,6 +241,70 @@ func TestServer(t *testing.T) {
t.Fatalf("expected postgres URL to start with \"postgres://\", got %q", got)
}
})
t.Run("SpammyLogs", func(t *testing.T) {
// The purpose of this test is to ensure we don't show excessive logs when the server starts.
t.Parallel()
inv, cfg := clitest.New(t,
"server",
"--in-memory",
"--http-address", ":0",
"--access-url", "http://localhost:3000/",
"--cache-dir", t.TempDir(),
)
stdoutRW := syncReaderWriter{}
stderrRW := syncReaderWriter{}
inv.Stdout = io.MultiWriter(os.Stdout, &stdoutRW)
inv.Stderr = io.MultiWriter(os.Stderr, &stderrRW)
clitest.Start(t, inv)
// Wait for startup
_ = waitAccessURL(t, cfg)
// Wait a bit for more logs to be printed.
time.Sleep(testutil.WaitShort)
// Lines containing these strings are printed because we're
// running the server with a test config. They wouldn't be
// normally shown to the user, so we'll ignore them.
ignoreLines := []string{
"isn't externally reachable",
"install.sh will be unavailable",
"telemetry disabled, unable to notify of security issues",
}
countLines := func(fullOutput string) int {
terminalWidth := 80
linesByNewline := strings.Split(fullOutput, "\n")
countByWidth := 0
lineLoop:
for _, line := range linesByNewline {
for _, ignoreLine := range ignoreLines {
if strings.Contains(line, ignoreLine) {
continue lineLoop
}
}
if line == "" {
// Empty lines take up one line.
countByWidth++
} else {
countByWidth += (len(line) + terminalWidth - 1) / terminalWidth
}
}
return countByWidth
}
stdout, err := io.ReadAll(&stdoutRW)
if err != nil {
t.Fatalf("failed to read stdout: %v", err)
}
stderr, err := io.ReadAll(&stderrRW)
if err != nil {
t.Fatalf("failed to read stderr: %v", err)
}
numLines := countLines(string(stdout)) + countLines(string(stderr))
require.Less(t, numLines, 20)
})
// Validate that a warning is printed that it may not be externally
// reachable.
@ -2140,3 +2205,22 @@ func mockTelemetryServer(t *testing.T) (*url.URL, chan *telemetry.Deployment, ch
return serverURL, deployment, snapshot
}
// syncWriter provides a thread-safe io.ReadWriter implementation
type syncReaderWriter struct {
buf bytes.Buffer
mu sync.Mutex
}
func (w *syncReaderWriter) Write(p []byte) (n int, err error) {
w.mu.Lock()
defer w.mu.Unlock()
return w.buf.Write(p)
}
func (w *syncReaderWriter) Read(p []byte) (n int, err error) {
w.mu.Lock()
defer w.mu.Unlock()
return w.buf.Read(p)
}