diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2025-04-09 14:30:54 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-04-11 13:02:25 +0000 |
| commit | 0bd6db418098e2d98a2edf948b41410d3d9f9e70 (patch) | |
| tree | 65a87774f63eadb75036b75c5294db051943de42 /syz-cluster | |
| parent | 27ba3dade815757a586b8f5a994ff675786ca212 (diff) | |
syz-cluster: share and display triage logs
For now, only share it for the skipped series.
Diffstat (limited to 'syz-cluster')
| -rw-r--r-- | syz-cluster/dashboard/handler.go | 12 | ||||
| -rw-r--r-- | syz-cluster/dashboard/templates/series.html | 7 | ||||
| -rw-r--r-- | syz-cluster/pkg/api/api.go | 3 | ||||
| -rw-r--r-- | syz-cluster/pkg/db/entities.go | 17 | ||||
| -rw-r--r-- | syz-cluster/pkg/db/migrations/1_initialize.up.sql | 1 | ||||
| -rw-r--r-- | syz-cluster/pkg/service/session.go | 14 | ||||
| -rw-r--r-- | syz-cluster/pkg/triage/tree.go | 1 | ||||
| -rw-r--r-- | syz-cluster/workflow/triage-step/main.go | 8 |
8 files changed, 50 insertions, 13 deletions
diff --git a/syz-cluster/dashboard/handler.go b/syz-cluster/dashboard/handler.go index c18436978..c17921351 100644 --- a/syz-cluster/dashboard/handler.go +++ b/syz-cluster/dashboard/handler.go @@ -57,6 +57,7 @@ var staticFs embed.FS func (h *dashboardHandler) Mux() *http.ServeMux { mux := http.NewServeMux() mux.HandleFunc("/sessions/{id}/log", errToStatus(h.sessionLog)) + mux.HandleFunc("/sessions/{id}/triage_log", errToStatus(h.sessionTriageLog)) mux.HandleFunc("/sessions/{id}/test_logs", errToStatus(h.sessionTestLog)) mux.HandleFunc("/sessions/{id}/test_artifacts", errToStatus(h.sessionTestArtifacts)) mux.HandleFunc("/series/{id}", errToStatus(h.seriesInfo)) @@ -223,6 +224,17 @@ func (h *dashboardHandler) sessionLog(w http.ResponseWriter, r *http.Request) er } // nolint:dupl +func (h *dashboardHandler) sessionTriageLog(w http.ResponseWriter, r *http.Request) error { + session, err := h.sessionRepo.GetByID(r.Context(), r.PathValue("id")) + if err != nil { + return err + } else if session == nil { + return fmt.Errorf("%w: session", errNotFound) + } + return h.streamBlob(w, session.TriageLogURI) +} + +// nolint:dupl func (h *dashboardHandler) patchContent(w http.ResponseWriter, r *http.Request) error { patch, err := h.seriesRepo.PatchByID(r.Context(), r.PathValue("id")) if err != nil { diff --git a/syz-cluster/dashboard/templates/series.html b/syz-cluster/dashboard/templates/series.html index 754bfe9e2..9a71e0053 100644 --- a/syz-cluster/dashboard/templates/series.html +++ b/syz-cluster/dashboard/templates/series.html @@ -99,7 +99,12 @@ {{if not .SkipReason.IsNull}} <tr> <th>Skipped</th> - <td>{{.SkipReason.StringVal}}</td> + <td> + {{.SkipReason.StringVal}} + {{if .TriageLogURI}} + <a href="/sessions/{{.ID}}/triage_log">[Log]</a> + {{end}} + </td> </tr> {{end}} {{if .LogURI}} diff --git a/syz-cluster/pkg/api/api.go b/syz-cluster/pkg/api/api.go index 1644b0ff0..33da0e5ff 100644 --- a/syz-cluster/pkg/api/api.go +++ b/syz-cluster/pkg/api/api.go @@ -13,7 +13,8 @@ type TriageResult struct { } type SkipRequest struct { - Reason string `json:"reason"` + Reason string `json:"reason"` + TriageLog []byte `json:"log"` } // The data layout faclitates the simplicity of the workflow definition. diff --git a/syz-cluster/pkg/db/entities.go b/syz-cluster/pkg/db/entities.go index 688bb8971..203ab32c9 100644 --- a/syz-cluster/pkg/db/entities.go +++ b/syz-cluster/pkg/db/entities.go @@ -60,14 +60,15 @@ const ( ) type Session struct { - ID string `spanner:"ID"` - SeriesID string `spanner:"SeriesID"` - CreatedAt time.Time `spanner:"CreatedAt"` - StartedAt spanner.NullTime `spanner:"StartedAt"` - FinishedAt spanner.NullTime `spanner:"FinishedAt"` - SkipReason spanner.NullString `spanner:"SkipReason"` - LogURI string `spanner:"LogURI"` - Tags []string `spanner:"Tags"` + ID string `spanner:"ID"` + SeriesID string `spanner:"SeriesID"` + CreatedAt time.Time `spanner:"CreatedAt"` + StartedAt spanner.NullTime `spanner:"StartedAt"` + FinishedAt spanner.NullTime `spanner:"FinishedAt"` + SkipReason spanner.NullString `spanner:"SkipReason"` + LogURI string `spanner:"LogURI"` + TriageLogURI string `spanner:"TriageLogURI"` + Tags []string `spanner:"Tags"` // TODO: to accept more specific fuzzing assignment, // add Triager, BaseRepo, BaseCommit, Config fields. } diff --git a/syz-cluster/pkg/db/migrations/1_initialize.up.sql b/syz-cluster/pkg/db/migrations/1_initialize.up.sql index c8938ca53..9935774c4 100644 --- a/syz-cluster/pkg/db/migrations/1_initialize.up.sql +++ b/syz-cluster/pkg/db/migrations/1_initialize.up.sql @@ -56,6 +56,7 @@ CREATE TABLE Sessions ( FinishedAt TIMESTAMP, SkipReason STRING(1024), LogURI STRING(512) NOT NULL, + TriageLogURI STRING(512) NOT NULL, Tags ARRAY<STRING(256)>, CONSTRAINT FK_SeriesSessions FOREIGN KEY (SeriesID) REFERENCES Series (ID), ) PRIMARY KEY(ID); diff --git a/syz-cluster/pkg/service/session.go b/syz-cluster/pkg/service/session.go index 23f1a8c17..9ad0688fd 100644 --- a/syz-cluster/pkg/service/session.go +++ b/syz-cluster/pkg/service/session.go @@ -4,31 +4,45 @@ package service import ( + "bytes" "context" "errors" + "fmt" "time" "github.com/google/syzkaller/syz-cluster/pkg/api" "github.com/google/syzkaller/syz-cluster/pkg/app" + "github.com/google/syzkaller/syz-cluster/pkg/blob" "github.com/google/syzkaller/syz-cluster/pkg/db" ) type SessionService struct { sessionRepo *db.SessionRepository seriesRepo *db.SeriesRepository + blobStorage blob.Storage } func NewSessionService(env *app.AppEnvironment) *SessionService { return &SessionService{ sessionRepo: db.NewSessionRepository(env.Spanner), seriesRepo: db.NewSeriesRepository(env.Spanner), + blobStorage: env.BlobStorage, } } var ErrSessionNotFound = errors.New("session not found") func (s *SessionService) SkipSession(ctx context.Context, sessionID string, skip *api.SkipRequest) error { + var triageLogURI string + if len(skip.TriageLog) > 0 { + var err error + triageLogURI, err = s.blobStorage.Store(bytes.NewReader(skip.TriageLog)) + if err != nil { + return fmt.Errorf("failed to save the log: %w", err) + } + } err := s.sessionRepo.Update(ctx, sessionID, func(session *db.Session) error { + session.TriageLogURI = triageLogURI session.SetSkipReason(skip.Reason) return nil }) diff --git a/syz-cluster/pkg/triage/tree.go b/syz-cluster/pkg/triage/tree.go index 592bbce78..61e8935f4 100644 --- a/syz-cluster/pkg/triage/tree.go +++ b/syz-cluster/pkg/triage/tree.go @@ -9,7 +9,6 @@ import ( "github.com/google/syzkaller/syz-cluster/pkg/api" ) -// TODO: add tests. func SelectTree(series *api.Series, trees []*api.Tree) *api.Tree { seriesCc := map[string]bool{} for _, cc := range series.Cc { diff --git a/syz-cluster/workflow/triage-step/main.go b/syz-cluster/workflow/triage-step/main.go index 14bae39f5..d61fc4947 100644 --- a/syz-cluster/workflow/triage-step/main.go +++ b/syz-cluster/workflow/triage-step/main.go @@ -4,9 +4,11 @@ package main import ( + "bytes" "context" "flag" "fmt" + "io" "os" "github.com/google/syzkaller/pkg/debugtracer" @@ -82,8 +84,9 @@ func getVerdict(ctx context.Context, client *api.Client, ops triage.TreeOps) (*a // TODO: the workflow step must be retried. return nil, fmt.Errorf("failed to query the last build: %w", err) } + var buf bytes.Buffer selector := triage.NewCommitSelector(ops, &debugtracer.GenericTracer{ - TraceWriter: os.Stderr, + TraceWriter: io.MultiWriter(os.Stderr, &buf), }) result, err := selector.Select(series, tree, lastBuild) if err != nil { @@ -92,7 +95,8 @@ func getVerdict(ctx context.Context, client *api.Client, ops triage.TreeOps) (*a } else if result.Commit == "" { return &api.TriageResult{ Skip: &api.SkipRequest{ - Reason: "failed to find the base commit: " + result.Reason, + Reason: "failed to find the base commit: " + result.Reason, + TriageLog: buf.Bytes(), }, }, nil } |
