Skip to content

fix: add constraint and runtime check for provisioner logs size limit #18893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Jul 31, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9f8cd50
add logs overflowed field to provisioner jobs and gen models
bcpeinhardt Jul 15, 2025
68d8e5e
update queries and make gen
bcpeinhardt Jul 15, 2025
476c6ff
add logs length field as well with constraint
bcpeinhardt Jul 15, 2025
c8de633
update queries
bcpeinhardt Jul 15, 2025
908c888
handle log size overflow on insertion
bcpeinhardt Jul 15, 2025
c709a9e
update sdk
bcpeinhardt Jul 15, 2025
f32ac68
implement dbauthz stubs
bcpeinhardt Jul 15, 2025
29ad77c
couple tests
bcpeinhardt Jul 15, 2025
f6134aa
initial frontend updates
bcpeinhardt Jul 15, 2025
cc469f8
runtime check possible overflow
bcpeinhardt Jul 21, 2025
29297d6
update log message to be less confusing
bcpeinhardt Jul 21, 2025
cd891db
Merge branch 'main' into bcpeinhardt/17992-fix-startup-logs-size-limi…
bcpeinhardt Jul 21, 2025
1398491
lint fixes
bcpeinhardt Jul 21, 2025
395c9e1
Merge branch 'main' into bcpeinhardt/17992-fix-startup-logs-size-limi…
bcpeinhardt Jul 21, 2025
630e2ac
rename migrations after conflicting merge
bcpeinhardt Jul 21, 2025
e44cd47
run make gen after migration
bcpeinhardt Jul 21, 2025
fa118db
Merge branch 'main' into bcpeinhardt/17992-fix-startup-logs-size-limi…
bcpeinhardt Jul 21, 2025
105de84
Merge branch 'main' into bcpeinhardt/17992-fix-startup-logs-size-limi…
bcpeinhardt Jul 29, 2025
2923e9d
Merge branch 'main' into bcpeinhardt/17992-fix-startup-logs-size-limi…
bcpeinhardt Jul 30, 2025
61a58f5
adjust migration numbers
bcpeinhardt Jul 30, 2025
e7f2ec6
update dbauthz and querymetrics for removed query
bcpeinhardt Jul 30, 2025
4a2a7f8
add rbac tests for provisioner job logs length and overflowed queries
bcpeinhardt Jul 30, 2025
8115e4a
reshuffling
bcpeinhardt Jul 30, 2025
99d5090
Merge branch 'main' into bcpeinhardt/17992-fix-startup-logs-size-limi…
bcpeinhardt Jul 30, 2025
c09f0f6
update migration numbers
bcpeinhardt Jul 30, 2025
1ab1347
remove period from slog log
bcpeinhardt Jul 30, 2025
6964cee
Merge branch 'main' into bcpeinhardt/17992-fix-startup-logs-size-limi…
bcpeinhardt Jul 30, 2025
a03a956
migration rename
bcpeinhardt Jul 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
reshuffling
  • Loading branch information
bcpeinhardt committed Jul 30, 2025
commit 8115e4aa31d75dd65a578717ec93b1a05ca326d7
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
ALTER TABLE provisioner_jobs ADD COLUMN logs_overflowed boolean NOT NULL DEFAULT false;

COMMENT ON COLUMN provisioner_jobs.logs_length IS 'Total length of provisioner logs';
COMMENT ON COLUMN provisioner_jobs.logs_overflowed IS 'Whether the provisioner logs overflowed in length';
COMMENT ON COLUMN provisioner_jobs.logs_overflowed IS 'Whether the provisioner logs overflowed in length';
74 changes: 48 additions & 26 deletions coderd/provisionerdserver/provisionerdserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -907,43 +907,65 @@ func (s *server) UpdateJob(ctx context.Context, request *proto.UpdateJobRequest)
insertParams := database.InsertProvisionerJobLogsParams{
JobID: parsedID,
}

newLogSize := 0
overflowedErrorMsg := "Provisioner logs exceeded the max size of 1MB. Will not continue to write provisioner logs for workspace build."
lenErrMsg := len(overflowedErrorMsg)

var (
createdAt time.Time
level database.LogLevel
stage string
source database.LogSource
output string
)

for _, log := range request.Logs {
logLevel, err := convertLogLevel(log.Level)
// Build our log params
level, err = convertLogLevel(log.Level)
if err != nil {
return nil, xerrors.Errorf("convert log level: %w", err)
}
logSource, err := convertLogSource(log.Source)
source, err = convertLogSource(log.Source)
if err != nil {
return nil, xerrors.Errorf("convert log source: %w", err)
}
insertParams.CreatedAt = append(insertParams.CreatedAt, time.UnixMilli(log.CreatedAt))
insertParams.Level = append(insertParams.Level, logLevel)
insertParams.Stage = append(insertParams.Stage, log.Stage)
insertParams.Source = append(insertParams.Source, logSource)
insertParams.Output = append(insertParams.Output, log.Output)
createdAt = time.UnixMilli(log.CreatedAt)
stage = log.Stage
output = log.Output

// Check if we would overflow the job logs (not leaving enough room for the error message)
willOverflow := int64(job.LogsLength)+int64(newLogSize)+int64(lenErrMsg)+int64(len(output)) > 1048576
if willOverflow {
s.Logger.Debug(ctx, "provisioner job logs overflowed 1MB size limit in database.", slog.F("job_id", parsedID))
err = s.Database.UpdateProvisionerJobLogsOverflowed(ctx, database.UpdateProvisionerJobLogsOverflowedParams{
ID: parsedID,
LogsOverflowed: true,
})
if err != nil {
s.Logger.Error(ctx, "failed to set logs overflowed flag", slog.F("job_id", parsedID), slog.Error(err))
}

level = database.LogLevelWarn
output = overflowedErrorMsg
}

newLogSize += len(output)

insertParams.CreatedAt = append(insertParams.CreatedAt, createdAt)
insertParams.Level = append(insertParams.Level, level)
insertParams.Stage = append(insertParams.Stage, stage)
insertParams.Source = append(insertParams.Source, source)
insertParams.Output = append(insertParams.Output, output)
s.Logger.Debug(ctx, "job log",
slog.F("job_id", parsedID),
slog.F("stage", log.Stage),
slog.F("output", log.Output))
}
slog.F("stage", stage),
slog.F("output", output))

newLogSize := 0
for _, log := range request.Logs {
newLogSize += len(log.Output)
}

willOverflow := int64(job.LogsLength)+int64(newLogSize) > 1048576
if willOverflow {
err = s.Database.UpdateProvisionerJobLogsOverflowed(ctx, database.UpdateProvisionerJobLogsOverflowedParams{
ID: parsedID,
LogsOverflowed: true,
})
if err != nil {
s.Logger.Error(ctx, "failed to set logs overflowed flag", slog.F("job_id", parsedID), slog.Error(err))
// Don't write any more logs because there's no room.
if willOverflow {
break
}
return &proto.UpdateJobResponse{
Canceled: job.CanceledAt.Valid,
}, nil
}

err = s.Database.UpdateProvisionerJobLogsLength(ctx, database.UpdateProvisionerJobLogsLengthParams{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ export const WorkspaceBuildLogs: FC<WorkspaceBuildLogsProps> = ({
created_at: new Date().toISOString(),
log_level: "error",
log_source: "provisioner",
output: "Provisioner logs exceeded the max size of 1MB!",
output:
"Provisioner logs exceeded the max size of 1MB. Will not continue to write provisioner logs for workspace build.",
stage: "overflow",
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ export const WorkspaceBuildPageView: FC<WorkspaceBuildPageViewProps> = ({
borderBottom: `1px solid ${theme.palette.divider}`,
}}
>
Provisioner logs exceeded the maximum size of 1MB and were
truncated.
Provisioner logs exceeded the max size of 1MB. Will not continue
to write provisioner logs for workspace build.
</Alert>
)}

Expand Down
Loading