feat: support bundle updates to enable pprof and telemetry collection (#21486)

- Adds pprof collection support now that we have the listeners
automatically starting (requires Coder server 2.28.0+, includes a
version check). Collects heap, allocs, profile (30s), block, mutex,
goroutine, threadcreate, trace (30s), cmdline, symbol. Performs capture
for 30 seconds and emits a log line stating as such. Enable capture by
supplying the `--pprof` flag or `CODER_SUPPORT_BUNDLE_PPROF` env var.
Collection of pprof data from both coderd and the Coder agent occurs.
- Adds collection of Prometheus metrics, also requires 2.28.0+
- Adds the ability to include a template in the bundle independently of
supplying the details of a running workspace by supplying the
`--template` flag or `CODER_SUPPORT_BUNDLE_TEMPLATE` env var
- Captures a list of workspaces the user has access to. Defaults to a
max of 10, configurable via `--workspaces-total-cap` /
`CODER_SUPPORT_BUNDLE_WORKSPACES_TOTAL_CAP`
- Collects additional stats from the coderd deployment (aggregated
workspace/session metrics), as well as entitlements via license and
dismissed health checks.

created with help from mux
This commit is contained in:
Rowan Smith
2026-01-20 10:28:52 +11:00
committed by GitHub
parent 9776dc16bd
commit b163b4c950
8 changed files with 951 additions and 19 deletions
+22
View File
@@ -46,6 +46,8 @@ func TestSupportBundle(t *testing.T) {
// Support bundle tests can share a single coderdtest instance.
var dc codersdk.DeploymentConfig
dc.Values = coderdtest.DeploymentValues(t)
dc.Values.Prometheus.Enable = true
secretValue := uuid.NewString()
seedSecretDeploymentOptions(t, &dc, secretValue)
client, closer, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
@@ -203,6 +205,10 @@ func assertBundleContents(t *testing.T, path string, wantWorkspace bool, wantAge
var v codersdk.DeploymentConfig
decodeJSONFromZip(t, f, &v)
require.NotEmpty(t, v, "deployment config should not be empty")
case "deployment/entitlements.json":
var v codersdk.Entitlements
decodeJSONFromZip(t, f, &v)
require.NotNil(t, v, "entitlements should not be nil")
case "deployment/experiments.json":
var v codersdk.Experiments
decodeJSONFromZip(t, f, &v)
@@ -211,6 +217,22 @@ func assertBundleContents(t *testing.T, path string, wantWorkspace bool, wantAge
var v healthsdk.HealthcheckReport
decodeJSONFromZip(t, f, &v)
require.NotEmpty(t, v, "health report should not be empty")
case "deployment/health_settings.json":
var v healthsdk.HealthSettings
decodeJSONFromZip(t, f, &v)
require.NotEmpty(t, v, "health settings should not be empty")
case "deployment/stats.json":
var v codersdk.DeploymentStats
decodeJSONFromZip(t, f, &v)
require.NotNil(t, v, "deployment stats should not be nil")
case "deployment/workspaces.json":
var v codersdk.Workspace
decodeJSONFromZip(t, f, &v)
require.NotNil(t, v, "deployment workspaces should not be nil")
case "deployment/prometheus.txt":
bs := readBytesFromZip(t, f)
require.NotEmpty(t, bs, "prometheus metrics should not be empty")
require.Contains(t, string(bs), "go_goroutines", "prometheus metrics should contain go runtime metrics")
case "network/connection_info.json":
var v workspacesdk.AgentConnectionInfo
decodeJSONFromZip(t, f, &v)