From 490a226b3ddcb151a60fc6ba4364851ad6e4aec4 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Thu, 2 Jun 2022 18:28:07 +0300 Subject: [PATCH 1/8] feat: Add support for pprof in `coder agent` --- cli/agent.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cli/agent.go b/cli/agent.go index 238a1e858923b..5b1ffae517e68 100644 --- a/cli/agent.go +++ b/cli/agent.go @@ -3,6 +3,7 @@ package cli import ( "context" "net/http" + _ "net/http/pprof" "net/url" "os" "path/filepath" @@ -25,7 +26,9 @@ import ( func workspaceAgent() *cobra.Command { var ( - auth string + auth string + pprofEnabled bool + pprofAddress string ) cmd := &cobra.Command{ Use: "agent", @@ -49,6 +52,11 @@ func workspaceAgent() *cobra.Command { logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug) client := codersdk.New(coderURL) + if pprofEnabled { + //nolint:revive + defer serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof")() + } + // exchangeToken returns a session token. // This is abstracted to allow for the same looping condition // regardless of instance identity auth type. @@ -139,5 +147,7 @@ func workspaceAgent() *cobra.Command { } cliflag.StringVarP(cmd.Flags(), &auth, "auth", "", "CODER_AGENT_AUTH", "token", "Specify the authentication type to use for the agent") + cliflag.BoolVarP(cmd.Flags(), &pprofEnabled, "pprof-enable", "", "CODER_AGENT_PPROF_ENABLE", false, "Enable serving pprof metrics on the address defined by --pprof-address.") + cliflag.StringVarP(cmd.Flags(), &pprofAddress, "pprof-address", "", "CODER_AGENT_PPROF_ADDRESS", "127.0.0.1:6060", "The address to serve pprof.") return cmd } From 10a86ded50159d87a1b2f6d1723b43c5ce57d54a Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 3 Jun 2022 12:25:58 +0300 Subject: [PATCH 2/8] feat: Allow USR1 signal to start pprof --- cli/agent.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/cli/agent.go b/cli/agent.go index 5b1ffae517e68..c4960c4a4a9da 100644 --- a/cli/agent.go +++ b/cli/agent.go @@ -3,10 +3,12 @@ package cli import ( "context" "net/http" - _ "net/http/pprof" + _ "net/http/pprof" //nolint: gosec "net/url" "os" + "os/signal" "path/filepath" + "syscall" "time" "cloud.google.com/go/compute/metadata" @@ -53,8 +55,24 @@ func workspaceAgent() *cobra.Command { client := codersdk.New(coderURL) if pprofEnabled { - //nolint:revive - defer serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof")() + srvClose := serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof") + defer srvClose() + } else { + // If pprof wasn't enabled at startup, allow a + // `kill -USR1 $agent_pid` to start it. + usr1 := make(chan os.Signal, 1) + signal.Notify(usr1, syscall.SIGUSR1) + go func() { + select { + case <-usr1: + signal.Stop(usr1) + srvClose := serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof") + defer srvClose() + case <-cmd.Context().Done(): + return + } + <-cmd.Context().Done() // Prevent defer close until done. + }() } // exchangeToken returns a session token. From c91637fb64a1d02c738577400fcc6eb73792afc0 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 3 Jun 2022 12:44:19 +0300 Subject: [PATCH 3/8] fix: Try to fix macOS test? --- cli/agent.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cli/agent.go b/cli/agent.go index c4960c4a4a9da..532b84ccb3b9f 100644 --- a/cli/agent.go +++ b/cli/agent.go @@ -54,15 +54,19 @@ func workspaceAgent() *cobra.Command { logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug) client := codersdk.New(coderURL) + usr1 := make(chan os.Signal, 1) if pprofEnabled { + close(usr1) srvClose := serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof") defer srvClose() } else { // If pprof wasn't enabled at startup, allow a // `kill -USR1 $agent_pid` to start it. - usr1 := make(chan os.Signal, 1) signal.Notify(usr1, syscall.SIGUSR1) go func() { + defer close(usr1) + defer signal.Stop(usr1) + select { case <-usr1: signal.Stop(usr1) @@ -160,6 +164,7 @@ func workspaceAgent() *cobra.Command { }, }) <-cmd.Context().Done() + <-usr1 // Wait for server to close (if started). return closer.Close() }, } From ec54e019cf44b9bde6ab963ff6fc2490cb428206 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 3 Jun 2022 14:56:57 +0300 Subject: [PATCH 4/8] fix: Disable USR1 on Windows (no signal) --- cli/agent.go | 22 ++-------------------- cli/agent_unix.go | 33 +++++++++++++++++++++++++++++++++ cli/agent_windows.go | 15 +++++++++++++++ 3 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 cli/agent_unix.go create mode 100644 cli/agent_windows.go diff --git a/cli/agent.go b/cli/agent.go index 532b84ccb3b9f..d43c1e5e687a8 100644 --- a/cli/agent.go +++ b/cli/agent.go @@ -6,9 +6,7 @@ import ( _ "net/http/pprof" //nolint: gosec "net/url" "os" - "os/signal" "path/filepath" - "syscall" "time" "cloud.google.com/go/compute/metadata" @@ -54,29 +52,14 @@ func workspaceAgent() *cobra.Command { logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug) client := codersdk.New(coderURL) - usr1 := make(chan os.Signal, 1) if pprofEnabled { - close(usr1) srvClose := serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof") defer srvClose() } else { // If pprof wasn't enabled at startup, allow a // `kill -USR1 $agent_pid` to start it. - signal.Notify(usr1, syscall.SIGUSR1) - go func() { - defer close(usr1) - defer signal.Stop(usr1) - - select { - case <-usr1: - signal.Stop(usr1) - srvClose := serveHandler(cmd.Context(), logger, nil, pprofAddress, "pprof") - defer srvClose() - case <-cmd.Context().Done(): - return - } - <-cmd.Context().Done() // Prevent defer close until done. - }() + srvClose := agentPPROFStartOnUSR1(cmd.Context(), logger, pprofAddress) + defer srvClose() } // exchangeToken returns a session token. @@ -164,7 +147,6 @@ func workspaceAgent() *cobra.Command { }, }) <-cmd.Context().Done() - <-usr1 // Wait for server to close (if started). return closer.Close() }, } diff --git a/cli/agent_unix.go b/cli/agent_unix.go new file mode 100644 index 0000000000000..a5c8150c1f9d6 --- /dev/null +++ b/cli/agent_unix.go @@ -0,0 +1,33 @@ +package cli + +import ( + "context" + "os" + "os/signal" + "syscall" + + "cdr.dev/slog" +) + +func agentPPROFStartOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress string) (srvClose func()) { + usr1 := make(chan os.Signal, 1) + signal.Notify(usr1, syscall.SIGUSR1) + go func() { + defer close(usr1) + defer signal.Stop(usr1) + + select { + case <-usr1: + signal.Stop(usr1) + srvClose := serveHandler(ctx, logger, nil, pprofAddress, "pprof") + defer srvClose() + case <-ctx.Done(): + return + } + <-ctx.Done() // Prevent defer close until done. + }() + + return func() { + <-usr1 // Wait until usr1 is closed, ensures srvClose was run. + } +} diff --git a/cli/agent_windows.go b/cli/agent_windows.go new file mode 100644 index 0000000000000..cc3c6d089d62c --- /dev/null +++ b/cli/agent_windows.go @@ -0,0 +1,15 @@ +package cli + +import ( + "context" + "os" + "os/signal" + "syscall" + + "cdr.dev/slog" +) + +// agentPPROFStartOnUSR1 is no-op on Windows (no SIGUSR1 signal). +func agentPPROFStartOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress string) (srvClose func()) { + return func() {} +} From 03ae4c0439cd399f244984504c9879748ca210b4 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 3 Jun 2022 15:01:11 +0300 Subject: [PATCH 5/8] fix: Make close func actually close --- cli/agent_unix.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/agent_unix.go b/cli/agent_unix.go index a5c8150c1f9d6..ecc925fe1f847 100644 --- a/cli/agent_unix.go +++ b/cli/agent_unix.go @@ -10,6 +10,8 @@ import ( ) func agentPPROFStartOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress string) (srvClose func()) { + ctx, cancel := context.WithCancel(ctx) + usr1 := make(chan os.Signal, 1) signal.Notify(usr1, syscall.SIGUSR1) go func() { @@ -28,6 +30,7 @@ func agentPPROFStartOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress }() return func() { + cancel() <-usr1 // Wait until usr1 is closed, ensures srvClose was run. } } From 610abb69210135ee8ef9ccfe608165c1bbcdb3e0 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 3 Jun 2022 15:05:28 +0300 Subject: [PATCH 6/8] chore: Improve naming --- cli/agent.go | 4 ++-- cli/agent_unix.go | 2 +- cli/agent_windows.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/agent.go b/cli/agent.go index d43c1e5e687a8..287f18f7fbefa 100644 --- a/cli/agent.go +++ b/cli/agent.go @@ -57,8 +57,8 @@ func workspaceAgent() *cobra.Command { defer srvClose() } else { // If pprof wasn't enabled at startup, allow a - // `kill -USR1 $agent_pid` to start it. - srvClose := agentPPROFStartOnUSR1(cmd.Context(), logger, pprofAddress) + // `kill -USR1 $agent_pid` to start it (on Unix). + srvClose := agentStartPPROFOnUSR1(cmd.Context(), logger, pprofAddress) defer srvClose() } diff --git a/cli/agent_unix.go b/cli/agent_unix.go index ecc925fe1f847..6b5ab1f881908 100644 --- a/cli/agent_unix.go +++ b/cli/agent_unix.go @@ -9,7 +9,7 @@ import ( "cdr.dev/slog" ) -func agentPPROFStartOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress string) (srvClose func()) { +func agentStartPPROFOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress string) (srvClose func()) { ctx, cancel := context.WithCancel(ctx) usr1 := make(chan os.Signal, 1) diff --git a/cli/agent_windows.go b/cli/agent_windows.go index cc3c6d089d62c..e147eb8a2877e 100644 --- a/cli/agent_windows.go +++ b/cli/agent_windows.go @@ -9,7 +9,7 @@ import ( "cdr.dev/slog" ) -// agentPPROFStartOnUSR1 is no-op on Windows (no SIGUSR1 signal). -func agentPPROFStartOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress string) (srvClose func()) { +// agentStartPPROFOnUSR1 is no-op on Windows (no SIGUSR1 signal). +func agentStartPPROFOnUSR1(ctx context.Context, logger slog.Logger, pprofAddress string) (srvClose func()) { return func() {} } From ae3049d8894e093da5cb193826b592fa2be84dc6 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 3 Jun 2022 15:18:37 +0300 Subject: [PATCH 7/8] fix: Fix imports --- cli/agent_windows.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cli/agent_windows.go b/cli/agent_windows.go index e147eb8a2877e..6635e350cf611 100644 --- a/cli/agent_windows.go +++ b/cli/agent_windows.go @@ -2,9 +2,6 @@ package cli import ( "context" - "os" - "os/signal" - "syscall" "cdr.dev/slog" ) From e146759c1666ccb518d48e891f296d5257748a96 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 3 Jun 2022 16:13:26 +0300 Subject: [PATCH 8/8] fix: Disable agent_unix.go on windows --- cli/agent_unix.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/agent_unix.go b/cli/agent_unix.go index 6b5ab1f881908..1a7dd3d854cd5 100644 --- a/cli/agent_unix.go +++ b/cli/agent_unix.go @@ -1,3 +1,5 @@ +//go:build !windows + package cli import (