feat: add e2e workspace build duration metric (#21739) · coder/coder@6035e45

15 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -89,6 +89,7 @@ type Options struct {

8989

PublishWorkspaceAgentLogsUpdateFn func(ctx context.Context, workspaceAgentID uuid.UUID, msg agentsdk.LogsNotifyMessage)

9090

NetworkTelemetryHandler func(batch []*tailnetproto.TelemetryEvent)

9191

BoundaryUsageTracker *boundaryusage.Tracker

92+

LifecycleMetrics *LifecycleMetrics

9293
9394

AccessURL *url.URL

9495

AppHostname string

@@ -170,6 +171,7 @@ func New(opts Options, workspace database.Workspace) *API {

170171

Database: opts.Database,

171172

Log: opts.Log,

172173

PublishWorkspaceUpdateFn: api.publishWorkspaceUpdate,

174+

Metrics: opts.LifecycleMetrics,

173175

}

174176
175177

api.AppsAPI = &AppsAPI{

Original file line numberDiff line numberDiff line change

@@ -4,6 +4,7 @@ import (

44

"context"

55

"database/sql"

66

"slices"

7+

"sync"

78

"time"

89
910

"github.com/google/uuid"

@@ -31,7 +32,9 @@ type LifecycleAPI struct {

3132

Log slog.Logger

3233

PublishWorkspaceUpdateFn func(context.Context, *database.WorkspaceAgent, wspubsub.WorkspaceEventKind) error

3334
34-

TimeNowFn func() time.Time // defaults to dbtime.Now()

35+

TimeNowFn func() time.Time // defaults to dbtime.Now()

36+

Metrics *LifecycleMetrics

37+

emitMetricsOnce sync.Once

3538

}

3639
3740

func (a *LifecycleAPI) now() time.Time {

@@ -125,6 +128,17 @@ func (a *LifecycleAPI) UpdateLifecycle(ctx context.Context, req *agentproto.Upda

125128

}

126129

}

127130
131+

// Emit build duration metric when agent transitions to a terminal startup state.

132+

// We only emit once per agent connection to avoid duplicate metrics.

133+

switch lifecycleState {

134+

case database.WorkspaceAgentLifecycleStateReady,

135+

database.WorkspaceAgentLifecycleStateStartTimeout,

136+

database.WorkspaceAgentLifecycleStateStartError:

137+

a.emitMetricsOnce.Do(func() {

138+

a.emitBuildDurationMetric(ctx, workspaceAgent.ResourceID)

139+

})

140+

}

141+
128142

return req.Lifecycle, nil

129143

}

130144