Log slow API requests with server spans and client timing

This commit is contained in:
Ian Gulliver
2026-10-21 14:45:19 -07:00
parent 671165ec71
commit b4c1dbab37
31 changed files with 458 additions and 185 deletions
+1 -1
View File
@@ -77,7 +77,7 @@ func (m *Manager) startAudit(ctx context.Context, projectID string) error {
if err != nil || active {
return err
}
head, err := git.BranchHead(project.RepoPath, project.DefaultBranch)
head, err := git.BranchHead(ctx, project.RepoPath, project.DefaultBranch)
if err != nil {
return err
}
+2 -2
View File
@@ -54,7 +54,7 @@ func (m *Manager) recoverMergeTurns(ctx context.Context, running []api.AgentSess
if err != nil {
return err
}
merging, err := git.MergeInProgress(task.WorktreePath)
merging, err := git.MergeInProgress(ctx, task.WorktreePath)
if err != nil {
return err
}
@@ -74,7 +74,7 @@ func (m *Manager) endMergeTurn(sessionID string, abort bool) {
return
}
if abort {
err := git.AbortMerge(t.dir)
err := git.AbortMerge(context.Background(), t.dir)
if err != nil {
slog.Error("abort unfinished merge", "session", sessionID, "err", err)
}
+2 -2
View File
@@ -161,7 +161,7 @@ func (m *Manager) ask(ctx context.Context, l *live, raw json.RawMessage) (string
if err != nil {
return "", err
}
behind, err := git.Behind(task.WorktreePath, project.DefaultBranch)
behind, err := git.Behind(ctx, task.WorktreePath, project.DefaultBranch)
if err != nil {
slog.Error("count commits behind default branch", "task", task.Id, "err", err)
}
@@ -182,7 +182,7 @@ func (m *Manager) ask(ctx context.Context, l *live, raw json.RawMessage) (string
func (m *Manager) commitBeforeSync(ctx context.Context, l *live, branch string) error {
unlock := m.lockTask(l.taskID)
defer unlock()
_, err := git.CommitAll(l.dir, "Work before merging "+branch, l.gitName, l.gitEmail)
_, err := git.CommitAll(ctx, l.dir, "Work before merging "+branch, l.gitName, l.gitEmail)
if err != nil {
return err
}
+2 -2
View File
@@ -278,7 +278,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
if err != nil {
return "", err
}
base, err = git.Head(from.WorktreePath)
base, err = git.Head(ctx, from.WorktreePath)
if err != nil {
return "", err
}
@@ -970,7 +970,7 @@ func (m *Manager) listTasksText(ctx context.Context) (string, error) {
if !listed {
b.WriteString("- no active tasks\n")
}
src, found, err := git.ReadFile(p.RepoPath, p.DefaultBranch, todo.File)
src, found, err := git.ReadFile(ctx, p.RepoPath, p.DefaultBranch, todo.File)
if err != nil {
return "", err
}
+4 -4
View File
@@ -15,7 +15,7 @@ func (m *Manager) prepareMainCommit(ctx context.Context, task api.Task, project
return "", "", err
}
env := git.IdentityEnv(user.GitName, user.GitEmail)
commit, err := git.SquashCommit(project.RepoPath, task.WorktreePath, project.DefaultBranch, squashMessage(task.MergeTitle, coAuthors), env, m.signer(ctx, user))
commit, err := git.SquashCommit(ctx, project.RepoPath, task.WorktreePath, project.DefaultBranch, squashMessage(task.MergeTitle, coAuthors), env, m.signer(ctx, user))
if err != nil || commit == "" {
return "", "", err
}
@@ -23,17 +23,17 @@ func (m *Manager) prepareMainCommit(ctx context.Context, task api.Task, project
if err != nil {
return "", "", err
}
notes, err := git.NoteCommit(project.RepoPath, commit, note, env)
notes, err := git.NoteCommit(ctx, project.RepoPath, commit, note, env)
return commit, notes, err
}
func advanceMainCheckout(project api.Project, commit, notes string) error {
pushed := git.Remote + "/" + project.DefaultBranch
err := git.AdvanceNotes(project.RepoPath, notes)
err := git.AdvanceNotes(context.Background(), project.RepoPath, notes)
if err != nil {
return fmt.Errorf("pushed %s to %s, but updating %s in the project checkout failed: %w", commit, pushed, git.NotesRef, err)
}
err = git.FastForward(project.RepoPath, commit)
err = git.FastForward(context.Background(), project.RepoPath, commit)
if err != nil {
return fmt.Errorf("pushed %s to %s, but fast-forwarding the project checkout failed: %w", commit, pushed, err)
}
+4 -4
View File
@@ -722,7 +722,7 @@ func (m *Manager) recordMessage(ctx context.Context, sess api.AgentSession, task
payload := map[string]any{"text": text}
if implementer {
head, err := git.Head(task.WorktreePath)
head, err := git.Head(ctx, task.WorktreePath)
if err != nil {
return nil, false, err
}
@@ -1190,7 +1190,7 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error {
return err
}
if (owner || landingBy != "") && !finished {
err := git.AbortMerge(l.dir)
err := git.AbortMerge(ctx, l.dir)
if err != nil {
slog.Error("abort unfinished merge", "session", l.id, "err", err)
}
@@ -1209,13 +1209,13 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error {
return nil
}
}
sha, err := git.CommitAll(l.dir, commitMessage(res), l.gitName, l.gitEmail)
sha, err := git.CommitAll(ctx, l.dir, commitMessage(res), l.gitName, l.gitEmail)
if err != nil {
slog.Error("commit turn", "session", l.id, "err", err)
m.recordError(l, fmt.Sprintf("byre couldn't commit the turn's work, so the turn counts as unfinished: %v", err))
finished = false
if owner {
err = git.AbortMerge(l.dir)
err = git.AbortMerge(ctx, l.dir)
if err != nil {
slog.Error("abort unfinished merge", "session", l.id, "err", err)
}
+3 -3
View File
@@ -123,15 +123,15 @@ func (m *Manager) gitFacts(ctx context.Context, t api.Task, p api.Project) (stor
if t.WorktreePath == "" {
return g, nil
}
tree, err := git.Snapshot(t.WorktreePath)
tree, err := git.Snapshot(ctx, t.WorktreePath)
if err != nil {
return g, err
}
g.UnmergedCommits, err = git.Ahead(t.WorktreePath, p.DefaultBranch)
g.UnmergedCommits, err = git.Ahead(ctx, t.WorktreePath, p.DefaultBranch)
if err != nil {
return g, err
}
g.UnmergedFiles, err = git.ChangedFileCount(t.WorktreePath, p.DefaultBranch, tree)
g.UnmergedFiles, err = git.ChangedFileCount(ctx, t.WorktreePath, p.DefaultBranch, tree)
if err != nil {
return g, err
}
+2 -2
View File
@@ -223,7 +223,7 @@ func pushLanded(ctx context.Context, project api.Project, commit string) (bool,
if err != nil {
return false, &unfinishedMergeError{fmt.Errorf("checking whether %s reached %s failed: %w", commit, target, err)}
}
landed, err := git.IsAncestor(project.RepoPath, commit, target)
landed, err := git.IsAncestor(ctx, project.RepoPath, commit, target)
if err != nil {
return false, &unfinishedMergeError{fmt.Errorf("checking whether %s reached %s failed: %w", commit, target, err)}
}
@@ -405,7 +405,7 @@ func (m *Manager) RemoveTask(ctx context.Context, task api.Task, project api.Pro
if err != nil {
return err
}
return git.RemoveWorktree(project.RepoPath, task.WorktreePath, task.Branch)
return git.RemoveWorktree(ctx, project.RepoPath, task.WorktreePath, task.Branch)
}
type setTitlesArgs struct {
+3 -3
View File
@@ -115,7 +115,7 @@ func (m *Manager) pushToMain(ctx context.Context, l *live, task api.Task, projec
if err != nil {
return "", err
}
_, err = git.CommitAll(l.dir, title, l.gitName, l.gitEmail)
_, err = git.CommitAll(ctx, l.dir, title, l.gitName, l.gitEmail)
if err != nil {
return "", err
}
@@ -130,7 +130,7 @@ func (m *Manager) pushToMain(ctx context.Context, l *live, task api.Task, projec
return "", err
}
if commit == "" {
err = git.Merge(l.dir, project.DefaultBranch, "Merge "+project.DefaultBranch, l.gitName, l.gitEmail)
err = git.Merge(ctx, l.dir, project.DefaultBranch, "Merge "+project.DefaultBranch, l.gitName, l.gitEmail)
return "", err
}
@@ -147,7 +147,7 @@ func (m *Manager) pushToMain(ctx context.Context, l *live, task api.Task, projec
if err != nil {
return "", err
}
err = git.Merge(l.dir, commit, fmt.Sprintf("Merge %s from %s", commit[:7], project.DefaultBranch), l.gitName, l.gitEmail)
err = git.Merge(ctx, l.dir, commit, fmt.Sprintf("Merge %s from %s", commit[:7], project.DefaultBranch), l.gitName, l.gitEmail)
if err != nil {
return "", fmt.Errorf("pushed %s to %s, but merging it back into this branch failed: %w", commit, pushed, err)
}
+4 -4
View File
@@ -119,7 +119,7 @@ func (m *Manager) beginReviews(ctx context.Context, ref store.SnapshotRef) error
if project.ReviewWorkflow == "" {
return finished(api.ReviewStateFailed, "", fmt.Sprintf("project %s has no review workflow", project.Name))
}
changes, err := git.Compare(project.RepoPath, project.DefaultBranch, snap.CommitSha, snap.TreeSha, "")
changes, err := git.Compare(ctx, project.RepoPath, project.DefaultBranch, snap.CommitSha, snap.TreeSha, "")
if err != nil {
return finished(api.ReviewStateFailed, project.ReviewWorkflow, fmt.Sprintf("byre couldn't compare snapshot %d with %s: %v", snap.N, project.DefaultBranch, err))
}
@@ -213,7 +213,7 @@ func (m *Manager) startReviewers(ctx context.Context, task api.Task, project api
func (m *Manager) launchReviewer(ctx context.Context, task api.Task, project api.Project, snap api.Snapshot, rv store.Reviewer, prompt string) {
r := rv.Review
err := git.AddDetachedWorktree(project.RepoPath, m.reviewDir(project.Id, r.Id), snap.CommitSha)
err := git.AddDetachedWorktree(ctx, project.RepoPath, m.reviewDir(project.Id, r.Id), snap.CommitSha)
if err == nil {
err = os.MkdirAll(m.reviewMediaDir(project.Id, r.Id), 0o755)
}
@@ -230,7 +230,7 @@ func (m *Manager) launchReviewer(ctx context.Context, task api.Task, project api
}
func (m *Manager) reviewPrompt(ctx context.Context, task api.Task, project api.Project, snap api.Snapshot, def api.WorkflowDefinition, stage string, inputs []api.Review) (string, error) {
changes, err := git.Compare(project.RepoPath, project.DefaultBranch, snap.CommitSha, snap.TreeSha, "")
changes, err := git.Compare(ctx, project.RepoPath, project.DefaultBranch, snap.CommitSha, snap.TreeSha, "")
if err != nil {
return "", err
}
@@ -600,7 +600,7 @@ func (m *Manager) cleanUpReviewer(r store.EndedReviewer) {
}
func (m *Manager) removeReviewDir(project api.Project, reviewID string) {
err := git.RemoveDetachedWorktree(project.RepoPath, m.reviewDir(project.Id, reviewID))
err := git.RemoveDetachedWorktree(context.Background(), project.RepoPath, m.reviewDir(project.Id, reviewID))
if err != nil {
slog.Error("remove review worktree", "review", reviewID, "err", err)
}
+3 -3
View File
@@ -134,7 +134,7 @@ func (m *Manager) takeSnapshot(ctx context.Context, t snapTarget, trigger api.Sn
}
}
tree, err := git.Snapshot(t.dir)
tree, err := git.Snapshot(ctx, t.dir)
if err != nil {
return nil, err
}
@@ -152,7 +152,7 @@ func (m *Manager) takeSnapshot(ctx context.Context, t snapTarget, trigger api.Sn
}
n := last.N + 1
commit, err := git.CommitSnapshot(t.dir, tree, git.SnapshotRef(t.taskID, n), fmt.Sprintf("byre snapshot %d (%s)", n, trigger), git.IdentityEnv(t.gitName, t.gitEmail))
commit, err := git.CommitSnapshot(ctx, t.dir, tree, git.SnapshotRef(t.taskID, n), fmt.Sprintf("byre snapshot %d (%s)", n, trigger), git.IdentityEnv(t.gitName, t.gitEmail))
if err != nil {
return nil, err
}
@@ -279,7 +279,7 @@ func (m *Manager) dropSnapshots(repo, taskID string) error {
st.mu.Lock()
defer st.mu.Unlock()
return git.DeleteSnapshotRefs(repo, taskID)
return git.DeleteSnapshotRefs(context.Background(), repo, taskID)
}
func (m *Manager) afterTool(l *live) claude.HookFunc {
+3 -3
View File
@@ -65,7 +65,7 @@ func (m *Manager) subtaskTools(l *live) []mcp.Tool {
if err != nil {
return "", err
}
base, err := git.Head(l.dir)
base, err := git.Head(ctx, l.dir)
if err != nil {
return "", err
}
@@ -372,7 +372,7 @@ func (m *Manager) closeMergedSubtask(ctx context.Context, t api.Task, parentID,
if err != nil || t.Status != api.TaskStatusActive {
return err
}
merged, err := git.IsAncestor(dir, t.Branch, "HEAD")
merged, err := git.IsAncestor(ctx, dir, t.Branch, "HEAD")
if err != nil || !merged {
return err
}
@@ -384,7 +384,7 @@ func (m *Manager) closeMergedSubtask(ctx context.Context, t api.Task, parentID,
if err != nil {
return err
}
head, err := git.Head(dir)
head, err := git.Head(ctx, dir)
if err != nil {
return err
}
+3 -3
View File
@@ -52,7 +52,7 @@ func (m *Manager) StartTodo(ctx context.Context, project api.Project, creator ap
if creator.GitName == "" || creator.GitEmail == "" {
return nil, ErrNoGitIdentity
}
src, found, err := git.ReadFile(project.RepoPath, project.DefaultBranch, todo.File)
src, found, err := git.ReadFile(ctx, project.RepoPath, project.DefaultBranch, todo.File)
if err != nil {
return nil, err
}
@@ -120,14 +120,14 @@ func (m *Manager) createTask(ctx context.Context, project api.Project, t api.Tas
t.CreatedAt = time.Now().UTC()
var err error
t.BaseRef, err = git.AddWorktree(project.RepoPath, t.WorktreePath, t.Branch, base)
t.BaseRef, err = git.AddWorktree(ctx, project.RepoPath, t.WorktreePath, t.Branch, base)
if err != nil {
return api.Task{}, err
}
err = m.store.CreateTask(ctx, t, nil, actor)
if err != nil {
rerr := git.RemoveWorktree(project.RepoPath, t.WorktreePath, t.Branch)
rerr := git.RemoveWorktree(ctx, project.RepoPath, t.WorktreePath, t.Branch)
if rerr != nil {
slog.Error("remove worktree of task not created", "task", t.Id, "err", rerr)
}
+2 -2
View File
@@ -355,7 +355,7 @@ func (m *Manager) recordStage(ctx context.Context, l *live) error {
if err != nil {
return err
}
head, err := git.Head(l.dir)
head, err := git.Head(ctx, l.dir)
if err != nil {
return err
}
@@ -411,7 +411,7 @@ func (m *Manager) nextStage(ctx context.Context, sessionID string) ([]string, er
return nil, err
}
if recorded == "" {
head, err := git.Head(task.WorktreePath)
head, err := git.Head(ctx, task.WorktreePath)
if err != nil {
return nil, err
}