Skip to content

Commit 05e62a3

Browse files
committed
Improve trace logging for pulls and processes (go-gitea#22633)
Backport go-gitea#22633 Our trace logging is far from perfect and is difficult to follow. This PR: * Add trace logging for process manager add and remove. * Fixes an errant read file for git refs in getMergeCommit * Brings in the pullrequest `String` and `ColorFormat` methods introduced in go-gitea#22568 * Adds a lot more logging in to testPR etc. Ref go-gitea#22578 --------- Signed-off-by: Andrew Thornton <art27@cantab.net>
1 parent ff20146 commit 05e62a3

File tree

9 files changed

+227
-148
lines changed

9 files changed

+227
-148
lines changed

Diff for: models/issues/pull.go

+60-6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"context"
1010
"fmt"
1111
"io"
12+
"strconv"
1213
"strings"
1314

1415
"code.gitea.io/gitea/models/db"
@@ -133,6 +134,27 @@ const (
133134
PullRequestStatusAncestor
134135
)
135136

137+
func (status PullRequestStatus) String() string {
138+
switch status {
139+
case PullRequestStatusConflict:
140+
return "CONFLICT"
141+
case PullRequestStatusChecking:
142+
return "CHECKING"
143+
case PullRequestStatusMergeable:
144+
return "MERGEABLE"
145+
case PullRequestStatusManuallyMerged:
146+
return "MANUALLY_MERGED"
147+
case PullRequestStatusError:
148+
return "ERROR"
149+
case PullRequestStatusEmpty:
150+
return "EMPTY"
151+
case PullRequestStatusAncestor:
152+
return "ANCESTOR"
153+
default:
154+
return strconv.Itoa(int(status))
155+
}
156+
}
157+
136158
// PullRequestFlow the flow of pull request
137159
type PullRequestFlow int
138160

@@ -204,6 +226,42 @@ func DeletePullsByBaseRepoID(ctx context.Context, repoID int64) error {
204226
return err
205227
}
206228

229+
// ColorFormat writes a colored string to identify this struct
230+
func (pr *PullRequest) ColorFormat(s fmt.State) {
231+
if pr == nil {
232+
log.ColorFprintf(s, "PR[%d]%s#%d[%s...%s:%s]",
233+
log.NewColoredIDValue(0),
234+
log.NewColoredValue("<nil>/<nil>"),
235+
log.NewColoredIDValue(0),
236+
log.NewColoredValue("<nil>"),
237+
log.NewColoredValue("<nil>/<nil>"),
238+
log.NewColoredValue("<nil>"),
239+
)
240+
return
241+
}
242+
243+
log.ColorFprintf(s, "PR[%d]", log.NewColoredIDValue(pr.ID))
244+
if pr.BaseRepo != nil {
245+
log.ColorFprintf(s, "%s#%d[%s...", log.NewColoredValue(pr.BaseRepo.FullName()),
246+
log.NewColoredIDValue(pr.Index), log.NewColoredValue(pr.BaseBranch))
247+
} else {
248+
log.ColorFprintf(s, "Repo[%d]#%d[%s...", log.NewColoredIDValue(pr.BaseRepoID),
249+
log.NewColoredIDValue(pr.Index), log.NewColoredValue(pr.BaseBranch))
250+
}
251+
if pr.HeadRepoID == pr.BaseRepoID {
252+
log.ColorFprintf(s, "%s]", log.NewColoredValue(pr.HeadBranch))
253+
} else if pr.HeadRepo != nil {
254+
log.ColorFprintf(s, "%s:%s]", log.NewColoredValue(pr.HeadRepo.FullName()), log.NewColoredValue(pr.HeadBranch))
255+
} else {
256+
log.ColorFprintf(s, "Repo[%d]:%s]", log.NewColoredIDValue(pr.HeadRepoID), log.NewColoredValue(pr.HeadBranch))
257+
}
258+
}
259+
260+
// String represents the pr as a simple string
261+
func (pr *PullRequest) String() string {
262+
return log.ColorFormatAsString(pr)
263+
}
264+
207265
// MustHeadUserName returns the HeadRepo's username if failed return blank
208266
func (pr *PullRequest) MustHeadUserName() string {
209267
if err := pr.LoadHeadRepo(); err != nil {
@@ -255,13 +313,9 @@ func (pr *PullRequest) LoadHeadRepoCtx(ctx context.Context) (err error) {
255313

256314
pr.HeadRepo, err = repo_model.GetRepositoryByIDCtx(ctx, pr.HeadRepoID)
257315
if err != nil && !repo_model.IsErrRepoNotExist(err) { // Head repo maybe deleted, but it should still work
258-
return fmt.Errorf("getRepositoryByID(head): %w", err)
316+
return fmt.Errorf("pr[%d].LoadHeadRepo[%d]: %w", pr.ID, pr.HeadRepoID, err)
259317
}
260-
pr.isHeadRepoLoaded = true
261-
}
262-
return nil
263318
}
264-
265319
// LoadHeadRepo loads the head repository
266320
func (pr *PullRequest) LoadHeadRepo() error {
267321
return pr.LoadHeadRepoCtx(db.DefaultContext)
@@ -290,7 +344,7 @@ func (pr *PullRequest) LoadBaseRepoCtx(ctx context.Context) (err error) {
290344

291345
pr.BaseRepo, err = repo_model.GetRepositoryByIDCtx(ctx, pr.BaseRepoID)
292346
if err != nil {
293-
return fmt.Errorf("repo_model.GetRepositoryByID(base): %w", err)
347+
return fmt.Errorf("pr[%d].LoadBaseRepo[%d]: %w", pr.ID, pr.BaseRepoID, err)
294348
}
295349
return nil
296350
}

Diff for: modules/log/colors.go

+7
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,13 @@ func (cv *ColoredValue) Format(s fmt.State, c rune) {
384384
s.Write(*cv.resetBytes)
385385
}
386386

387+
// ColorFormatAsString returns the result of the ColorFormat without the color
388+
func ColorFormatAsString(colorVal ColorFormatted) string {
389+
s := new(strings.Builder)
390+
_, _ = ColorFprintf(&protectedANSIWriter{w: s, mode: removeColor}, "%-v", colorVal)
391+
return s.String()
392+
}
393+
387394
// SetColorBytes will allow a user to set the colorBytes of a colored value
388395
func (cv *ColoredValue) SetColorBytes(colorBytes []byte) {
389396
cv.colorBytes = &colorBytes

Diff for: modules/log/log.go

+11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"runtime"
1111
"strings"
1212
"sync"
13+
14+
"code.gitea.io/gitea/modules/process"
1315
)
1416

1517
type loggerMap struct {
@@ -286,6 +288,15 @@ func (l *LoggerAsWriter) Log(msg string) {
286288
}
287289

288290
func init() {
291+
process.Trace = func(start bool, pid process.IDType, description string, parentPID process.IDType, typ string) {
292+
if start && parentPID != "" {
293+
Log(1, TRACE, "Start %s: %s (from %s) (%s)", NewColoredValue(pid, FgHiYellow), description, NewColoredValue(parentPID, FgYellow), NewColoredValue(typ, Reset))
294+
} else if start {
295+
Log(1, TRACE, "Start %s: %s (%s)", NewColoredValue(pid, FgHiYellow), description, NewColoredValue(typ, Reset))
296+
} else {
297+
Log(1, TRACE, "Done %s: %s", NewColoredValue(pid, FgHiYellow), NewColoredValue(description, Reset))
298+
}
299+
}
289300
_, filename, _, _ := runtime.Caller(0)
290301
prefix = strings.TrimSuffix(filename, "modules/log/log.go")
291302
if prefix == filename {

Diff for: modules/process/manager.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package process
77

88
import (
99
"context"
10+
"log"
1011
"runtime/pprof"
1112
"strconv"
1213
"sync"
@@ -44,6 +45,18 @@ type IDType string
4445
// - it is simply an alias for context.CancelFunc and is only for documentary purposes
4546
type FinishedFunc = context.CancelFunc
4647

48+
var Trace = defaultTrace // this global can be overridden by particular logging packages - thus avoiding import cycles
49+
50+
func defaultTrace(start bool, pid IDType, description string, parentPID IDType, typ string) {
51+
if start && parentPID != "" {
52+
log.Printf("start process %s: %s (from %s) (%s)", pid, description, parentPID, typ)
53+
} else if start {
54+
log.Printf("start process %s: %s (%s)", pid, description, typ)
55+
} else {
56+
log.Printf("end process %s: %s", pid, description)
57+
}
58+
}
59+
4760
// Manager manages all processes and counts PIDs.
4861
type Manager struct {
4962
mutex sync.Mutex
@@ -155,6 +168,7 @@ func (pm *Manager) Add(ctx context.Context, description string, cancel context.C
155168

156169
pm.processMap[pid] = process
157170
pm.mutex.Unlock()
171+
Trace(true, pid, description, parentPID, processType)
158172

159173
pprofCtx := pprof.WithLabels(ctx, pprof.Labels(DescriptionPProfLabel, description, PPIDPProfLabel, string(parentPID), PIDPProfLabel, string(pid), ProcessTypePProfLabel, processType))
160174
if currentlyRunning {
@@ -186,18 +200,12 @@ func (pm *Manager) nextPID() (start time.Time, pid IDType) {
186200
return start, pid
187201
}
188202

189-
// Remove a process from the ProcessManager.
190-
func (pm *Manager) Remove(pid IDType) {
191-
pm.mutex.Lock()
192-
delete(pm.processMap, pid)
193-
pm.mutex.Unlock()
194-
}
195-
196203
func (pm *Manager) remove(process *process) {
197204
pm.mutex.Lock()
198205
defer pm.mutex.Unlock()
199206
if p := pm.processMap[process.PID]; p == process {
200207
delete(pm.processMap, process.PID)
208+
Trace(false, process.PID, process.Description, process.ParentPID, process.Type)
201209
}
202210
}
203211

Diff for: modules/process/manager_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func TestManager_Remove(t *testing.T) {
8383

8484
assert.NotEqual(t, GetContext(p1Ctx).GetPID(), GetContext(p2Ctx).GetPID(), "expected to get different pids got %s == %s", GetContext(p2Ctx).GetPID(), GetContext(p1Ctx).GetPID())
8585

86-
pm.Remove(GetPID(p2Ctx))
86+
finished()
8787

8888
_, exists := pm.processMap[GetPID(p2Ctx)]
8989
assert.False(t, exists, "PID %d is in the list but shouldn't", GetPID(p2Ctx))

Diff for: routers/web/repo/pull.go

+23-28
Original file line numberDiff line numberDiff line change
@@ -912,59 +912,54 @@ func MergePullRequest(ctx *context.Context) {
912912
pr := issue.PullRequest
913913
pr.Issue = issue
914914
pr.Issue.Repo = ctx.Repo.Repository
915-
manuallMerge := repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged
915+
manualMerge := repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged
916916
forceMerge := form.ForceMerge != nil && *form.ForceMerge
917917

918918
// start with merging by checking
919-
if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, manuallMerge, forceMerge); err != nil {
920-
if errors.Is(err, pull_service.ErrIsClosed) {
919+
if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, manualMerge, forceMerge); err != nil {
920+
switch {
921+
case errors.Is(err, pull_service.ErrIsClosed):
921922
if issue.IsPull {
922923
ctx.Flash.Error(ctx.Tr("repo.pulls.is_closed"))
923-
ctx.Redirect(issue.Link())
924924
} else {
925925
ctx.Flash.Error(ctx.Tr("repo.issues.closed_title"))
926-
ctx.Redirect(issue.Link())
927926
}
928-
} else if errors.Is(err, pull_service.ErrUserNotAllowedToMerge) {
927+
case errors.Is(err, pull_service.ErrUserNotAllowedToMerge):
929928
ctx.Flash.Error(ctx.Tr("repo.pulls.update_not_allowed"))
930-
ctx.Redirect(issue.Link())
931-
} else if errors.Is(err, pull_service.ErrHasMerged) {
929+
case errors.Is(err, pull_service.ErrHasMerged):
932930
ctx.Flash.Error(ctx.Tr("repo.pulls.has_merged"))
933-
ctx.Redirect(issue.Link())
934-
} else if errors.Is(err, pull_service.ErrIsWorkInProgress) {
931+
case errors.Is(err, pull_service.ErrIsWorkInProgress):
935932
ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_wip"))
936-
ctx.Redirect(issue.Link())
937-
} else if errors.Is(err, pull_service.ErrNotMergableState) {
933+
case errors.Is(err, pull_service.ErrNotMergableState):
938934
ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_not_ready"))
939-
ctx.Redirect(issue.Link())
940-
} else if models.IsErrDisallowedToMerge(err) {
935+
case models.IsErrDisallowedToMerge(err):
941936
ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_not_ready"))
942-
ctx.Redirect(issue.Link())
943-
} else if asymkey_service.IsErrWontSign(err) {
944-
ctx.Flash.Error(err.Error()) // has not translation ...
945-
ctx.Redirect(issue.Link())
946-
} else if errors.Is(err, pull_service.ErrDependenciesLeft) {
937+
case asymkey_service.IsErrWontSign(err):
938+
ctx.Flash.Error(err.Error()) // has no translation ...
939+
case errors.Is(err, pull_service.ErrDependenciesLeft):
947940
ctx.Flash.Error(ctx.Tr("repo.issues.dependency.pr_close_blocked"))
948-
ctx.Redirect(issue.Link())
949-
} else {
941+
default:
950942
ctx.ServerError("WebCheck", err)
943+
return
951944
}
945+
946+
ctx.Redirect(issue.Link())
952947
return
953948
}
954949

955950
// handle manually-merged mark
956-
if manuallMerge {
951+
if manualMerge {
957952
if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
958-
if models.IsErrInvalidMergeStyle(err) {
953+
switch {
954+
955+
case models.IsErrInvalidMergeStyle(err):
959956
ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
960-
ctx.Redirect(issue.Link())
961-
} else if strings.Contains(err.Error(), "Wrong commit ID") {
957+
case strings.Contains(err.Error(), "Wrong commit ID"):
962958
ctx.Flash.Error(ctx.Tr("repo.pulls.wrong_commit_id"))
963-
ctx.Redirect(issue.Link())
964-
} else {
959+
default:
965960
ctx.ServerError("MergedManually", err)
961+
return
966962
}
967-
return
968963
}
969964

970965
ctx.Redirect(issue.Link())

Diff for: services/automerge/automerge.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func getPullRequestsByHeadSHA(ctx context.Context, sha string, repo *repo_model.
165165

166166
func handlePull(pullID int64, sha string) {
167167
ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(),
168-
fmt.Sprintf("Handle AutoMerge of pull[%d] with sha[%s]", pullID, sha))
168+
fmt.Sprintf("Handle AutoMerge of PR[%d] with sha[%s]", pullID, sha))
169169
defer finished()
170170

171171
pr, err := issues_model.GetPullRequestByID(ctx, pullID)
@@ -177,7 +177,7 @@ func handlePull(pullID int64, sha string) {
177177
// Check if there is a scheduled pr in the db
178178
exists, scheduledPRM, err := pull_model.GetScheduledMergeByPullID(ctx, pr.ID)
179179
if err != nil {
180-
log.Error("pull[%d] GetScheduledMergeByPullID: %v", pr.ID, err)
180+
log.Error("%-v GetScheduledMergeByPullID: %v", pr, err)
181181
return
182182
}
183183
if !exists {
@@ -189,54 +189,54 @@ func handlePull(pullID int64, sha string) {
189189
// did not succeed or was not finished yet.
190190

191191
if err = pr.LoadHeadRepoCtx(ctx); err != nil {
192-
log.Error("pull[%d] LoadHeadRepoCtx: %v", pr.ID, err)
192+
log.Error("%-v LoadHeadRepo: %v", pr, err)
193193
return
194194
}
195195

196196
headGitRepo, err := git.OpenRepository(ctx, pr.HeadRepo.RepoPath())
197197
if err != nil {
198-
log.Error("OpenRepository: %v", err)
198+
log.Error("OpenRepository %-v: %v", pr.HeadRepo, err)
199199
return
200200
}
201201
defer headGitRepo.Close()
202202

203203
headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
204204

205205
if pr.HeadRepo == nil || !headBranchExist {
206-
log.Warn("Head branch of auto merge pr does not exist [HeadRepoID: %d, Branch: %s, PR ID: %d]", pr.HeadRepoID, pr.HeadBranch, pr.ID)
206+
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
207207
return
208208
}
209209

210210
// Check if all checks succeeded
211211
pass, err := pull_service.IsPullCommitStatusPass(ctx, pr)
212212
if err != nil {
213-
log.Error("IsPullCommitStatusPass: %v", err)
213+
log.Error("%-v IsPullCommitStatusPass: %v", pr, err)
214214
return
215215
}
216216
if !pass {
217-
log.Info("Scheduled auto merge pr has unsuccessful status checks [PullID: %d]", pr.ID)
217+
log.Info("Scheduled auto merge %-v has unsuccessful status checks", pr)
218218
return
219219
}
220220

221221
// Merge if all checks succeeded
222222
doer, err := user_model.GetUserByIDCtx(ctx, scheduledPRM.DoerID)
223223
if err != nil {
224-
log.Error("GetUserByIDCtx: %v", err)
224+
log.Error("Unable to get scheduled User[%d]: %v", scheduledPRM.DoerID, err)
225225
return
226226
}
227227

228228
perm, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, doer)
229229
if err != nil {
230-
log.Error("GetUserRepoPermission: %v", err)
230+
log.Error("GetUserRepoPermission %-v: %v", pr.HeadRepo, err)
231231
return
232232
}
233233

234234
if err := pull_service.CheckPullMergable(ctx, doer, &perm, pr, false, false); err != nil {
235235
if errors.Is(pull_service.ErrUserNotAllowedToMerge, err) {
236-
log.Info("PR %d was scheduled to automerge by an unauthorized user", pr.ID)
236+
log.Info("%-v was scheduled to automerge by an unauthorized user", pr)
237237
return
238238
}
239-
log.Error("pull[%d] CheckPullMergable: %v", pr.ID, err)
239+
log.Error("%-v CheckPullMergable: %v", pr, err)
240240
return
241241
}
242242

@@ -245,13 +245,13 @@ func handlePull(pullID int64, sha string) {
245245
baseGitRepo = headGitRepo
246246
} else {
247247
if err = pr.LoadBaseRepoCtx(ctx); err != nil {
248-
log.Error("LoadBaseRepoCtx: %v", err)
248+
log.Error("%-v LoadBaseRepo: %v", pr, err)
249249
return
250250
}
251251

252252
baseGitRepo, err = git.OpenRepository(ctx, pr.BaseRepo.RepoPath())
253253
if err != nil {
254-
log.Error("OpenRepository: %v", err)
254+
log.Error("OpenRepository %-v: %v", pr.BaseRepo, err)
255255
return
256256
}
257257
defer baseGitRepo.Close()

0 commit comments

Comments
 (0)