diff --git a/enterprise/cli/create_test.go b/enterprise/cli/create_test.go index b6699430b8..03d31a14e8 100644 --- a/enterprise/cli/create_test.go +++ b/enterprise/cli/create_test.go @@ -17,6 +17,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace/noop" "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbtestutil" @@ -370,6 +371,7 @@ func TestEnterpriseCreateWithPreset(t *testing.T) { prometheus.NewRegistry(), notifications.NewNoopEnqueuer(), newNoopUsageCheckerPtr(), + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer) @@ -481,6 +483,7 @@ func TestEnterpriseCreateWithPreset(t *testing.T) { prometheus.NewRegistry(), notifications.NewNoopEnqueuer(), newNoopUsageCheckerPtr(), + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer) diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index 3cb7514ee5..0beef07acb 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -1307,6 +1307,6 @@ func (api *API) setupPrebuilds(featureEnabled bool) (agplprebuilds.Reconciliatio } reconciler := prebuilds.NewStoreReconciler(api.Database, api.Pubsub, api.AGPL.FileCache, api.DeploymentValues.Prebuilds, - api.Logger.Named("prebuilds"), quartz.NewReal(), api.PrometheusRegistry, api.NotificationsEnqueuer, api.AGPL.BuildUsageChecker) + api.Logger.Named("prebuilds"), quartz.NewReal(), api.PrometheusRegistry, api.NotificationsEnqueuer, api.AGPL.BuildUsageChecker, api.TracerProvider) return reconciler, prebuilds.NewEnterpriseClaimer(api.Database) } diff --git a/enterprise/coderd/prebuilds/claim_test.go b/enterprise/coderd/prebuilds/claim_test.go index d4326a4fd0..7f4ffc0f28 100644 --- a/enterprise/coderd/prebuilds/claim_test.go +++ b/enterprise/coderd/prebuilds/claim_test.go @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace/noop" "golang.org/x/xerrors" "github.com/coder/coder/v2/coderd/database/dbtime" @@ -167,7 +168,7 @@ func TestClaimPrebuild(t *testing.T) { defer provisionerCloser.Close() cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - reconciler := prebuilds.NewStoreReconciler(spy, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(spy, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(spy) api.AGPL.PrebuildsClaimer.Store(&claimer) diff --git a/enterprise/coderd/prebuilds/metricscollector_test.go b/enterprise/coderd/prebuilds/metricscollector_test.go index aa9886fb7a..d45a175e17 100644 --- a/enterprise/coderd/prebuilds/metricscollector_test.go +++ b/enterprise/coderd/prebuilds/metricscollector_test.go @@ -6,11 +6,11 @@ import ( "testing" "github.com/google/uuid" - "github.com/stretchr/testify/require" - "tailscale.com/types/ptr" - "github.com/prometheus/client_golang/prometheus" prometheus_client "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace/noop" + "tailscale.com/types/ptr" "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/v2/coderd/coderdtest" @@ -197,7 +197,7 @@ func TestMetricsCollector(t *testing.T) { clock := quartz.NewMock(t) db, pubsub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ctx := testutil.Context(t, testutil.WaitLong) createdUsers := []uuid.UUID{database.PrebuildsSystemUserID} @@ -329,7 +329,7 @@ func TestMetricsCollector_DuplicateTemplateNames(t *testing.T) { clock := quartz.NewMock(t) db, pubsub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ctx := testutil.Context(t, testutil.WaitLong) collector := prebuilds.NewMetricsCollector(db, logger, reconciler) @@ -477,7 +477,7 @@ func TestMetricsCollector_ReconciliationPausedMetric(t *testing.T) { db, pubsub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) registry := prometheus.NewPedanticRegistry() - reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), registry, newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), registry, newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ctx := testutil.Context(t, testutil.WaitLong) // Ensure no pause setting is set (default state) @@ -506,7 +506,7 @@ func TestMetricsCollector_ReconciliationPausedMetric(t *testing.T) { db, pubsub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) registry := prometheus.NewPedanticRegistry() - reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), registry, newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), registry, newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ctx := testutil.Context(t, testutil.WaitLong) // Set reconciliation to paused @@ -535,7 +535,7 @@ func TestMetricsCollector_ReconciliationPausedMetric(t *testing.T) { db, pubsub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) registry := prometheus.NewPedanticRegistry() - reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), registry, newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, pubsub, cache, codersdk.PrebuildsConfig{}, logger, quartz.NewMock(t), registry, newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ctx := testutil.Context(t, testutil.WaitLong) // Set reconciliation back to not paused diff --git a/enterprise/coderd/prebuilds/reconcile.go b/enterprise/coderd/prebuilds/reconcile.go index 17a56d484c..416ccfa394 100644 --- a/enterprise/coderd/prebuilds/reconcile.go +++ b/enterprise/coderd/prebuilds/reconcile.go @@ -16,6 +16,8 @@ import ( "github.com/hashicorp/go-multierror" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "golang.org/x/sync/errgroup" "golang.org/x/xerrors" @@ -31,6 +33,7 @@ import ( "github.com/coder/coder/v2/coderd/prebuilds" "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/coderd/rbac/policy" + "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/coderd/wsbuilder" "github.com/coder/coder/v2/codersdk" sdkproto "github.com/coder/coder/v2/provisionersdk/proto" @@ -47,6 +50,7 @@ type StoreReconciler struct { registerer prometheus.Registerer notifEnq notifications.Enqueuer buildUsageChecker *atomic.Pointer[wsbuilder.UsageChecker] + tracer trace.Tracer cancelFn context.CancelCauseFunc running atomic.Bool @@ -89,6 +93,7 @@ func NewStoreReconciler(store database.Store, registerer prometheus.Registerer, notifEnq notifications.Enqueuer, buildUsageChecker *atomic.Pointer[wsbuilder.UsageChecker], + tracerProvider trace.TracerProvider, ) *StoreReconciler { reconciler := &StoreReconciler{ store: store, @@ -100,6 +105,7 @@ func NewStoreReconciler(store database.Store, registerer: registerer, notifEnq: notifEnq, buildUsageChecker: buildUsageChecker, + tracer: tracerProvider.Tracer(tracing.TracerName), done: make(chan struct{}, 1), provisionNotifyCh: make(chan database.ProvisionerJob, 10), } @@ -283,6 +289,9 @@ func (c *StoreReconciler) Stop(ctx context.Context, cause error) { // simultaneously for the same preset, but once both jobs have completed the reconciliation loop will notice the // extraneous instance and delete it. func (c *StoreReconciler) ReconcileAll(ctx context.Context) (stats prebuilds.ReconcileStats, err error) { + ctx, span := c.tracer.Start(ctx, "prebuilds.ReconcileAll") + defer span.End() + start := c.clock.Now() defer func() { stats.Elapsed = c.clock.Since(start) @@ -420,6 +429,9 @@ func (c *StoreReconciler) reportHardLimitedPresets(snapshot *prebuilds.GlobalSna // SnapshotState captures the current state of all prebuilds across templates. func (c *StoreReconciler) SnapshotState(ctx context.Context, store database.Store) (*prebuilds.GlobalSnapshot, error) { + ctx, span := c.tracer.Start(ctx, "prebuilds.SnapshotState") + defer span.End() + if err := ctx.Err(); err != nil { return nil, err } @@ -482,13 +494,21 @@ func (c *StoreReconciler) SnapshotState(ctx context.Context, store database.Stor }, &database.TxOptions{ Isolation: sql.LevelRepeatableRead, // This mirrors the MVCC snapshotting Postgres does when using CTEs ReadOnly: true, - TxIdentifier: "prebuilds_state_determination", + TxIdentifier: "prebuilds.SnapshotState", }) return &state, err } func (c *StoreReconciler) ReconcilePreset(ctx context.Context, ps prebuilds.PresetSnapshot) error { + ctx, span := c.tracer.Start(ctx, "prebuilds.ReconcilePreset", trace.WithAttributes( + attribute.String("preset_id", ps.Preset.ID.String()), + attribute.String("preset_name", ps.Preset.Name), + attribute.String("template_id", ps.Preset.TemplateID.String()), + attribute.String("template_name", ps.Preset.TemplateName), + )) + defer span.End() + logger := c.logger.With( slog.F("template_id", ps.Preset.TemplateID.String()), slog.F("template_name", ps.Preset.TemplateName), @@ -554,6 +574,9 @@ func (c *StoreReconciler) WithReconciliationLock( logger slog.Logger, fn func(ctx context.Context, db database.Store) error, ) error { + ctx, span := c.tracer.Start(ctx, "prebuilds.WithReconciliationLock") + defer span.End() + // This tx holds a global lock, which prevents any other coderd replica from starting a reconciliation and // possibly getting an inconsistent view of the state. // @@ -574,8 +597,10 @@ func (c *StoreReconciler) WithReconciliationLock( } if !acquired { // Normal case: another replica has the lock + span.SetAttributes(attribute.Bool("lock_acquired", false)) return nil } + span.SetAttributes(attribute.Bool("lock_acquired", true)) logger.Debug(ctx, "acquired top-level reconciliation lock", @@ -586,7 +611,7 @@ func (c *StoreReconciler) WithReconciliationLock( }, &database.TxOptions{ Isolation: sql.LevelRepeatableRead, ReadOnly: true, - TxIdentifier: "prebuilds", + TxIdentifier: "prebuilds.WithReconciliationLock", }) } @@ -599,6 +624,13 @@ func (c *StoreReconciler) WithReconciliationLock( // This method handles logging at appropriate levels and performs the necessary operations // according to the action type. It returns an error if any part of the action fails. func (c *StoreReconciler) executeReconciliationAction(ctx context.Context, logger slog.Logger, ps prebuilds.PresetSnapshot, action *prebuilds.ReconciliationActions) error { + ctx, span := c.tracer.Start(ctx, "prebuilds.executeReconciliationAction", trace.WithAttributes( + attribute.Int("action_type", int(action.ActionType)), + attribute.Int("create_count", int(action.Create)), + attribute.Int("delete_count", len(action.DeleteIDs)), + )) + defer span.End() + levelFn := logger.Debug // Nothing has to be done. @@ -692,6 +724,13 @@ func (c *StoreReconciler) executeReconciliationAction(ctx context.Context, logge } func (c *StoreReconciler) createPrebuiltWorkspace(ctx context.Context, prebuiltWorkspaceID uuid.UUID, templateID uuid.UUID, presetID uuid.UUID) error { + ctx, span := c.tracer.Start(ctx, "prebuilds.createPrebuiltWorkspace", trace.WithAttributes( + attribute.String("prebuild_id", prebuiltWorkspaceID.String()), + attribute.String("template_id", templateID.String()), + attribute.String("preset_id", presetID.String()), + )) + defer span.End() + name, err := prebuilds.GenerateName() if err != nil { return xerrors.Errorf("failed to generate unique prebuild ID: %w", err) @@ -736,8 +775,9 @@ func (c *StoreReconciler) createPrebuiltWorkspace(ctx context.Context, prebuiltW provisionerJob, err = c.provision(ctx, db, prebuiltWorkspaceID, template, presetID, database.WorkspaceTransitionStart, workspace, DeprovisionModeNormal) return err }, &database.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: false, + Isolation: sql.LevelRepeatableRead, + ReadOnly: false, + TxIdentifier: "prebuilds.createPrebuiltWorkspace", }) if err != nil { return err @@ -788,6 +828,13 @@ func (c *StoreReconciler) provisionDelete(ctx context.Context, db database.Store // Since these jobs were never processed by a provisioner, no Terraform resources were created, // making it safe to orphan-delete the workspaces (skipping Terraform destroy). func (c *StoreReconciler) cancelAndOrphanDeletePendingPrebuilds(ctx context.Context, templateID uuid.UUID, templateVersionID uuid.UUID, presetID uuid.UUID) error { + ctx, span := c.tracer.Start(ctx, "prebuilds.cancelAndOrphanDeletePendingPrebuilds", trace.WithAttributes( + attribute.String("template_id", templateID.String()), + attribute.String("template_version_id", templateVersionID.String()), + attribute.String("preset_id", presetID.String()), + )) + defer span.End() + var canceledProvisionerJob *database.ProvisionerJob var canceledWorkspaceID uuid.UUID err := c.store.InTx(func(db database.Store) error { @@ -832,8 +879,9 @@ func (c *StoreReconciler) cancelAndOrphanDeletePendingPrebuilds(ctx context.Cont return multiErr.ErrorOrNil() }, &database.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: false, + Isolation: sql.LevelRepeatableRead, + ReadOnly: false, + TxIdentifier: "prebuilds.cancelAndOrphanDeletePendingPrebuilds", }) if err != nil { return err @@ -851,13 +899,21 @@ func (c *StoreReconciler) cancelAndOrphanDeletePendingPrebuilds(ctx context.Cont } func (c *StoreReconciler) deletePrebuiltWorkspace(ctx context.Context, prebuiltWorkspaceID uuid.UUID, templateID uuid.UUID, presetID uuid.UUID) error { + ctx, span := c.tracer.Start(ctx, "prebuilds.deletePrebuiltWorkspace", trace.WithAttributes( + attribute.String("prebuild_id", prebuiltWorkspaceID.String()), + attribute.String("template_id", templateID.String()), + attribute.String("preset_id", presetID.String()), + )) + defer span.End() + var provisionerJob *database.ProvisionerJob err := c.store.InTx(func(db database.Store) (err error) { provisionerJob, err = c.provisionDelete(ctx, db, prebuiltWorkspaceID, templateID, presetID, DeprovisionModeNormal) return err }, &database.TxOptions{ - Isolation: sql.LevelRepeatableRead, - ReadOnly: false, + Isolation: sql.LevelRepeatableRead, + ReadOnly: false, + TxIdentifier: "prebuilds.deletePrebuiltWorkspace", }) if err != nil { return err @@ -879,6 +935,16 @@ func (c *StoreReconciler) provision( workspace database.Workspace, mode DeprovisionMode, ) (*database.ProvisionerJob, error) { + ctx, span := c.tracer.Start(ctx, "prebuilds.provision", trace.WithAttributes( + attribute.String("prebuild_id", prebuildID.String()), + attribute.String("template_id", template.ID.String()), + attribute.String("preset_id", presetID.String()), + attribute.String("transition", string(transition)), + attribute.String("workspace_id", workspace.ID.String()), + attribute.String("mode", mode.String()), + )) + defer span.End() + tvp, err := db.GetPresetParametersByTemplateVersionID(ctx, template.ActiveVersionID) if err != nil { return nil, xerrors.Errorf("fetch preset details: %w", err) @@ -920,8 +986,12 @@ func (c *StoreReconciler) provision( builder = builder.Orphan() } + // Strip trace context - provisionerd is a separate service and should + // start its own trace rather than continuing the prebuilds trace. + buildCtx := trace.ContextWithSpan(ctx, tracing.NoopSpan) + _, provisionerJob, _, err := builder.Build( - ctx, + buildCtx, db, c.fileCache, func(_ policy.Action, _ rbac.Objecter) bool { diff --git a/enterprise/coderd/prebuilds/reconcile_test.go b/enterprise/coderd/prebuilds/reconcile_test.go index 7548faebd7..cdbac86f97 100644 --- a/enterprise/coderd/prebuilds/reconcile_test.go +++ b/enterprise/coderd/prebuilds/reconcile_test.go @@ -13,6 +13,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace/noop" "golang.org/x/xerrors" "tailscale.com/types/ptr" @@ -52,7 +53,7 @@ func TestNoReconciliationActionsIfNoPresets(t *testing.T) { } logger := testutil.Logger(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // given a template version with no presets org := dbgen.Organization(t, db, database.Organization{}) @@ -95,7 +96,7 @@ func TestNoReconciliationActionsIfNoPrebuilds(t *testing.T) { } logger := testutil.Logger(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // given there are presets, but no prebuilds org := dbgen.Organization(t, db, database.Organization{}) @@ -425,7 +426,7 @@ func (tc testCase) run(t *testing.T) { pubSub = &brokenPublisher{Pubsub: pubSub} } cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // Run the reconciliation multiple times to ensure idempotency // 8 was arbitrary, but large enough to reasonably trust the result @@ -494,7 +495,7 @@ func TestMultiplePresetsPerTemplateVersion(t *testing.T) { ).Leveled(slog.LevelDebug) db, pubSub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ownerID := uuid.New() dbgen.User(t, db, database.User{ @@ -617,7 +618,7 @@ func TestPrebuildScheduling(t *testing.T) { ).Leveled(slog.LevelDebug) db, pubSub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ownerID := uuid.New() dbgen.User(t, db, database.User{ @@ -718,7 +719,7 @@ func TestInvalidPreset(t *testing.T) { ).Leveled(slog.LevelDebug) db, pubSub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ownerID := uuid.New() dbgen.User(t, db, database.User{ @@ -780,7 +781,7 @@ func TestDeletionOfPrebuiltWorkspaceWithInvalidPreset(t *testing.T) { ).Leveled(slog.LevelDebug) db, pubSub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ownerID := uuid.New() dbgen.User(t, db, database.User{ @@ -874,7 +875,7 @@ func TestSkippingHardLimitedPresets(t *testing.T) { fakeEnqueuer := newFakeEnqueuer() registry := prometheus.NewRegistry() cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // Set up test environment with a template, version, and preset. ownerID := uuid.New() @@ -1017,7 +1018,7 @@ func TestHardLimitedPresetShouldNotBlockDeletion(t *testing.T) { fakeEnqueuer := newFakeEnqueuer() registry := prometheus.NewRegistry() cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // Set up test environment with a template, version, and preset. ownerID := uuid.New() @@ -1211,7 +1212,7 @@ func TestRunLoop(t *testing.T) { ).Leveled(slog.LevelDebug) db, pubSub := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - reconciler := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) ownerID := uuid.New() dbgen.User(t, db, database.User{ @@ -1339,7 +1340,7 @@ func TestFailedBuildBackoff(t *testing.T) { ).Leveled(slog.LevelDebug) db, ps := dbtestutil.NewDB(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - reconciler := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // Given: an active template version with presets and prebuilds configured. const desiredInstances = 2 @@ -1461,7 +1462,7 @@ func TestReconciliationLock(t *testing.T) { quartz.NewMock(t), prometheus.NewRegistry(), newNoopEnqueuer(), - newNoopUsageCheckerPtr()) + newNoopUsageCheckerPtr(), noop.NewTracerProvider()) reconciler.WithReconciliationLock(ctx, logger, func(_ context.Context, _ database.Store) error { lockObtained := mutex.TryLock() // As long as the postgres lock is held, this mutex should always be unlocked when we get here. @@ -1491,7 +1492,7 @@ func TestTrackResourceReplacement(t *testing.T) { fakeEnqueuer := newFakeEnqueuer() registry := prometheus.NewRegistry() cache := files.New(registry, &coderdtest.FakeAuthorizer{}) - reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // Given: a template admin to receive a notification. templateAdmin := dbgen.User(t, db, database.User{ @@ -1643,7 +1644,7 @@ func TestExpiredPrebuildsMultipleActions(t *testing.T) { fakeEnqueuer := newFakeEnqueuer() registry := prometheus.NewRegistry() cache := files.New(registry, &coderdtest.FakeAuthorizer{}) - controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr()) + controller := prebuilds.NewStoreReconciler(db, pubSub, cache, cfg, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // Set up test environment with a template, version, and preset ownerID := uuid.New() @@ -2098,7 +2099,7 @@ func TestCancelPendingPrebuilds(t *testing.T) { registry := prometheus.NewRegistry() cache := files.New(registry, &coderdtest.FakeAuthorizer{}) logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: false}).Leveled(slog.LevelDebug) - reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr(), noop.NewTracerProvider()) owner := coderdtest.CreateFirstUser(t, client) // Given: a template with a version containing a preset with 1 prebuild instance @@ -2335,7 +2336,7 @@ func TestCancelPendingPrebuilds(t *testing.T) { registry := prometheus.NewRegistry() cache := files.New(registry, &coderdtest.FakeAuthorizer{}) logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: false}).Leveled(slog.LevelDebug) - reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr(), noop.NewTracerProvider()) owner := coderdtest.CreateFirstUser(t, client) // Given: template A with 2 versions @@ -2400,7 +2401,7 @@ func TestReconciliationStats(t *testing.T) { registry := prometheus.NewRegistry() cache := files.New(registry, &coderdtest.FakeAuthorizer{}) logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: false}).Leveled(slog.LevelDebug) - reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr(), noop.NewTracerProvider()) owner := coderdtest.CreateFirstUser(t, client) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort) @@ -2911,7 +2912,7 @@ func TestReconciliationRespectsPauseSetting(t *testing.T) { } logger := testutil.Logger(t) cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) - reconciler := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr()) + reconciler := prebuilds.NewStoreReconciler(db, ps, cache, cfg, logger, clock, prometheus.NewRegistry(), newNoopEnqueuer(), newNoopUsageCheckerPtr(), noop.NewTracerProvider()) // Setup a template with a preset that should create prebuilds org := dbgen.Organization(t, db, database.Organization{}) diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go index b7508b3ff8..cce911f944 100644 --- a/enterprise/coderd/workspaces_test.go +++ b/enterprise/coderd/workspaces_test.go @@ -18,6 +18,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace/noop" "cdr.dev/slog" "cdr.dev/slog/sloggers/slogtest" @@ -1986,6 +1987,7 @@ func TestPrebuildsAutobuild(t *testing.T) { prometheus.NewRegistry(), notificationsNoop, api.AGPL.BuildUsageChecker, + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer) @@ -2108,6 +2110,7 @@ func TestPrebuildsAutobuild(t *testing.T) { prometheus.NewRegistry(), notificationsNoop, api.AGPL.BuildUsageChecker, + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer) @@ -2230,6 +2233,7 @@ func TestPrebuildsAutobuild(t *testing.T) { prometheus.NewRegistry(), notificationsNoop, api.AGPL.BuildUsageChecker, + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer) @@ -2374,6 +2378,7 @@ func TestPrebuildsAutobuild(t *testing.T) { prometheus.NewRegistry(), notificationsNoop, api.AGPL.BuildUsageChecker, + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer) @@ -2519,6 +2524,7 @@ func TestPrebuildsAutobuild(t *testing.T) { prometheus.NewRegistry(), notificationsNoop, api.AGPL.BuildUsageChecker, + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer) @@ -2964,6 +2970,7 @@ func TestWorkspaceProvisionerdServerMetrics(t *testing.T) { prometheus.NewRegistry(), notifications.NewNoopEnqueuer(), api.AGPL.BuildUsageChecker, + noop.NewTracerProvider(), ) var claimer agplprebuilds.Claimer = prebuilds.NewEnterpriseClaimer(db) api.AGPL.PrebuildsClaimer.Store(&claimer)