diff --git a/alpine/distributionscanner.go b/alpine/distributionscanner.go index 1f95bc020..b9179c085 100644 --- a/alpine/distributionscanner.go +++ b/alpine/distributionscanner.go @@ -6,12 +6,11 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "regexp" "runtime/trace" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/osrelease" @@ -61,12 +60,10 @@ func (*DistributionScanner) Kind() string { return scannerKind } // If the files are found but all regexp fail to match an empty slice is returned. func (s *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "alpine/DistributionScanner.Scan", + slog.DebugContext(ctx, "start", "version", s.Version(), "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + defer slog.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { return nil, fmt.Errorf("alpine: unable to open layer: %w", err) @@ -102,13 +99,13 @@ func readOSRelease(ctx context.Context, sys fs.FS) (*claircore.Distribution, err return nil, err } if id := m[`ID`]; id != `alpine` { - zlog.Debug(ctx).Str("id", id).Msg("seemingly not alpine") + slog.DebugContext(ctx, "seemingly not alpine", "id", id) break } vid := m[`VERSION_ID`] idx := strings.LastIndexByte(vid, '.') if idx == -1 { - zlog.Debug(ctx).Str("val", vid).Msg("martian VERSION_ID") + slog.DebugContext(ctx, "martian VERSION_ID", "val", vid) break } v := vid[:idx] @@ -126,9 +123,9 @@ func readOSRelease(ctx context.Context, sys fs.FS) (*claircore.Distribution, err PrettyName: m[`PRETTY_NAME`], }, nil case errors.Is(err, fs.ErrNotExist): - zlog.Debug(ctx). - Str("path", osrelease.Path). - Msg("file doesn't exist") + slog.DebugContext(ctx, + "file doesn't exist", + "path", osrelease.Path) default: return nil, err } @@ -153,7 +150,7 @@ func readIssue(ctx context.Context, sys fs.FS) (*claircore.Distribution, error) ms := issueRegexp.FindSubmatch(b) if ms == nil { - zlog.Debug(ctx).Msg("seemingly not alpine") + slog.DebugContext(ctx, "seemingly not alpine") break } v := string(ms[1]) @@ -164,9 +161,9 @@ func readIssue(ctx context.Context, sys fs.FS) (*claircore.Distribution, error) PrettyName: fmt.Sprintf(`Alpine Linux v%s`, v), }, nil case errors.Is(err, fs.ErrNotExist): - zlog.Debug(ctx). - Str("path", issuePath). - Msg("file doesn't exist") + slog.DebugContext(ctx, + "file doesn't exist", + "path", issuePath) default: return nil, err } diff --git a/alpine/distributionscanner_test.go b/alpine/distributionscanner_test.go index b21adc1e3..50a8fb20a 100644 --- a/alpine/distributionscanner_test.go +++ b/alpine/distributionscanner_test.go @@ -8,14 +8,13 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" + "github.com/quay/claircore/test" ) func TestScanFs(t *testing.T) { - ctx := context.Background() - ctx = zlog.Test(ctx, t) + ctx := test.Logging(t) td := os.DirFS("testdata") ms, err := fs.Glob(td, "3.*") @@ -46,7 +45,6 @@ func scanFsTestcase(ctx context.Context, sys fs.FS) func(*testing.T) { if err != nil { t.Fatal(err) } - ctx := zlog.Test(ctx, t) got, err := s.scanFs(ctx, sys) if err != nil { t.Error(err) diff --git a/alpine/fetcher.go b/alpine/fetcher.go index f496ab94a..717172352 100644 --- a/alpine/fetcher.go +++ b/alpine/fetcher.go @@ -4,27 +4,24 @@ import ( "context" "fmt" "io" + "log/slog" "net/http" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" "github.com/quay/claircore/pkg/tmp" ) func (u *updater) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "alpine/Updater.Fetch") - - zlog.Info(ctx).Str("database", u.url).Msg("starting fetch") + slog.InfoContext(ctx, "starting fetch", "database", u.url) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.url, nil) if err != nil { return nil, hint, fmt.Errorf("alpine: unable to construct request: %w", err) } if hint != "" { - zlog.Debug(ctx). - Str("hint", string(hint)). - Msg("using hint") + slog.DebugContext(ctx, + "using hint", + "hint", string(hint)) req.Header.Set("if-none-match", string(hint)) } @@ -41,25 +38,27 @@ func (u *updater) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCl } fallthrough case http.StatusNotModified: - zlog.Info(ctx).Msg("database unchanged since last fetch") + slog.InfoContext(ctx, "database unchanged since last fetch") return nil, hint, driver.Unchanged default: return nil, hint, fmt.Errorf("alpine: http response error: %s %d", res.Status, res.StatusCode) } - zlog.Debug(ctx).Msg("successfully requested database") + slog.DebugContext(ctx, "successfully requested database") tf, err := tmp.NewFile("", u.Name()+".") if err != nil { return nil, hint, fmt.Errorf("alpine: unable to open tempfile: %w", err) } - zlog.Debug(ctx). - Str("name", tf.Name()). - Msg("created tempfile") + slog.DebugContext(ctx, + "created tempfile", + "name", tf.Name()) var success bool defer func() { if !success { if err := tf.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + slog.WarnContext(ctx, + "unable to close spool", + "reason", err) } } }() @@ -71,13 +70,13 @@ func (u *updater) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCl if n, err := tf.Seek(0, io.SeekStart); err != nil || n != 0 { return nil, hint, fmt.Errorf("alpine: unable to seek database to start: at %d, %v", n, err) } - zlog.Debug(ctx).Msg("decompressed and buffered database") + slog.DebugContext(ctx, "decompressed and buffered database") success = true hint = driver.Fingerprint(res.Header.Get("etag")) - zlog.Debug(ctx). - Str("hint", string(hint)). - Msg("using new hint") + slog.DebugContext(ctx, + "using new hint", + "hint", string(hint)) return tf, hint, nil } diff --git a/alpine/fetcher_test.go b/alpine/fetcher_test.go index aa2b93e45..5388fc669 100644 --- a/alpine/fetcher_test.go +++ b/alpine/fetcher_test.go @@ -1,13 +1,13 @@ package alpine import ( - "context" "net/http" "net/http/httptest" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" + + "github.com/quay/claircore/test" ) func serveSecDB(t *testing.T) (string, *http.Client) { @@ -17,7 +17,8 @@ func serveSecDB(t *testing.T) (string, *http.Client) { } func TestFactory(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) + root, c := serveSecDB(t) fac := &Factory{} err := fac.Configure(ctx, func(v any) error { diff --git a/alpine/parser.go b/alpine/parser.go index 015faae33..b0d6bf400 100644 --- a/alpine/parser.go +++ b/alpine/parser.go @@ -4,8 +4,7 @@ import ( "context" "encoding/json" "io" - - "github.com/quay/zlog" + "log/slog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" @@ -18,8 +17,8 @@ const ( var _ driver.Parser = (*updater)(nil) func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "alpine/Updater.Parse") - zlog.Info(ctx).Msg("starting parse") + slog.InfoContext(ctx, "parse start") + defer slog.InfoContext(ctx, "parse done") defer r.Close() var db SecurityDB diff --git a/alpine/parser_test.go b/alpine/parser_test.go index 2ecc05df7..4de7777d7 100644 --- a/alpine/parser_test.go +++ b/alpine/parser_test.go @@ -8,9 +8,9 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" + "github.com/quay/claircore/test" ) var dist310 = stableRelease{3, 10}.Distribution() @@ -128,8 +128,8 @@ var v3_10CommunityTruncatedVulns = []*claircore.Vulnerability{ func TestParser(t *testing.T) { t.Parallel() - ctx := context.Background() - var table = []struct { + ctx := test.Logging(t) + table := []struct { release release repo string testFile string @@ -145,7 +145,8 @@ func TestParser(t *testing.T) { for _, test := range table { t.Run(test.testFile, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx, done := context.WithCancel(ctx) + t.Cleanup(done) path := fmt.Sprintf("testdata/%s", test.testFile) f, err := os.Open(path) diff --git a/alpine/secdb_test.go b/alpine/secdb_test.go index f0e3cb749..51ba73c95 100644 --- a/alpine/secdb_test.go +++ b/alpine/secdb_test.go @@ -48,7 +48,7 @@ var v3_10CommunityTruncatedSecDB = SecurityDB{ } func TestSecDBParse(t *testing.T) { - var table = []struct { + table := []struct { testFile string expected SecurityDB }{ diff --git a/alpine/updater.go b/alpine/updater.go index d8c7c4371..8e444da7d 100644 --- a/alpine/updater.go +++ b/alpine/updater.go @@ -4,14 +4,13 @@ import ( "bytes" "context" "fmt" + "log/slog" "net/http" "net/url" "path" "strings" "sync" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" ) @@ -60,11 +59,10 @@ func NewFactory(_ context.Context) (*Factory, error) { // UpdaterSet implements driver.UpdaterSetFactory. func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { - ctx = zlog.ContextWithValues(ctx, "component", "alpine/Factory.UpdaterSet") s := driver.NewUpdaterSet() if f.c == nil { - zlog.Info(ctx). - Msg("unconfigured") + slog.InfoContext(ctx, + "unconfigured") return s, nil } @@ -81,9 +79,9 @@ func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { if f.etag != "" { req.Header.Set(`if-none-match`, f.etag) } - zlog.Debug(ctx). - Stringer("url", u). - Msg("making request") + slog.DebugContext(ctx, + "making request", + "url", u) res, err := f.c.Do(req) if err != nil { return s, fmt.Errorf("alpine: error requesting %q: %w", u.String(), err) @@ -91,9 +89,9 @@ func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { defer res.Body.Close() switch res.StatusCode { case http.StatusNotModified: - zlog.Debug(ctx). - Stringer("url", u). - Msg("not modified") + slog.DebugContext(ctx, + "not modified", + "url", u) return f.cur, nil case http.StatusOK: default: @@ -127,12 +125,12 @@ Major: if err != nil { return s, fmt.Errorf("alpine: unable to construct request: %w", err) } - ctx := zlog.ContextWithValues(ctx, "url", u.String(), "release", r.String()) + l := slog.With("url", u, "release", r) req, err := http.NewRequestWithContext(ctx, http.MethodHead, u.String(), nil) if err != nil { return s, fmt.Errorf("alpine: unable to construct request: %w", err) } - zlog.Debug(ctx).Msg("checking release") + l.DebugContext(ctx, "checking release") res, err := f.c.Do(req) if err != nil { return s, fmt.Errorf("alpine: error requesting %q: %w", u.String(), err) @@ -143,13 +141,13 @@ Major: foundLower = true todo = append(todo, r) case http.StatusNotFound: - zlog.Debug(ctx).Msg("not found") + l.DebugContext(ctx, "not found") if foundLower { break Minor } break Major default: - zlog.Info(ctx).Str("status", res.Status).Msg("unexpected status reported") + l.InfoContext(ctx, "unexpected status reported", "status", res.Status) } } } @@ -159,12 +157,12 @@ Major: if err != nil { return s, fmt.Errorf("alpine: unable to construct request: %w", err) } - ctx := zlog.ContextWithValues(ctx, "url", u.String(), "release", r.String(), "repo", n) + l := slog.With("url", u, "release", r, "repo", n) req, err := http.NewRequestWithContext(ctx, http.MethodHead, u.String(), nil) if err != nil { return s, fmt.Errorf("alpine: unable to construct request: %w", err) } - zlog.Debug(ctx).Msg("checking repository") + l.DebugContext(ctx, "checking repository") res, err := f.c.Do(req) if err != nil { return s, fmt.Errorf("alpine: error requesting %q: %w", u.String(), err) @@ -172,12 +170,12 @@ Major: res.Body.Close() switch res.StatusCode { case http.StatusOK: - zlog.Debug(ctx).Msg("found") + l.DebugContext(ctx, "found") case http.StatusNotFound: - zlog.Debug(ctx).Msg("not found") + l.DebugContext(ctx, "not found") continue default: - zlog.Info(ctx).Str("status", res.Status).Msg("unexpected status reported") + l.InfoContext(ctx, "unexpected status reported", "status", res.Status) continue } s.Add(&updater{ @@ -247,10 +245,9 @@ func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c * } if cfg.URL != "" { u.url = cfg.URL - zlog.Info(ctx). - Str("component", "alpine/Updater.Configure"). - Str("updater", u.Name()). - Msg("configured url") + slog.InfoContext(ctx, + "configured url", + "updater", u.Name()) } u.client = c return nil diff --git a/apk/scanner.go b/apk/scanner.go index 519e2000d..3ad6e2d01 100644 --- a/apk/scanner.go +++ b/apk/scanner.go @@ -6,10 +6,9 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -51,13 +50,12 @@ func (*Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore. } defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "apk/Scanner.Scan", + log := slog.With( "version", version, "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + log.DebugContext(ctx, "start") + defer log.DebugContext(ctx, "done") sys, err := layer.FS() if err != nil { @@ -71,7 +69,7 @@ func (*Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore. default: return nil, err } - zlog.Debug(ctx).Msg("found database") + log.DebugContext(ctx, "found database") pkgs := []*claircore.Package{} srcs := make(map[string]*claircore.Package) @@ -118,7 +116,7 @@ func (*Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore. } pkgs = append(pkgs, &p) } - zlog.Debug(ctx).Int("count", len(pkgs)).Msg("found packages") + log.DebugContext(ctx, "found packages", "count", len(pkgs)) return pkgs, nil } diff --git a/apk/scanner_test.go b/apk/scanner_test.go index 21009b995..7fc0c8df8 100644 --- a/apk/scanner_test.go +++ b/apk/scanner_test.go @@ -1,11 +1,9 @@ package apk import ( - "context" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" @@ -13,7 +11,7 @@ import ( func TestScan(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) // TODO(hank) Turn into a fixture. want := []*claircore.Package{ { diff --git a/aws/client.go b/aws/client.go index 7e1de3575..511c33464 100644 --- a/aws/client.go +++ b/aws/client.go @@ -7,14 +7,13 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "path" "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore/aws/internal/alas" "github.com/quay/claircore/internal/xmlutil" "github.com/quay/claircore/pkg/tmp" @@ -29,16 +28,17 @@ const ( // Client is an http for accessing ALAS mirrors. type Client struct { c *http.Client + log *slog.Logger mirrors []*url.URL } func NewClient(ctx context.Context, hc *http.Client, release Release) (*Client, error) { - ctx = zlog.ContextWithValues(ctx, "release", string(release)) if hc == nil { return nil, errors.New("http.Client not provided") } client := &Client{ c: hc, + log: slog.With("release", string(release)), mirrors: []*url.URL{}, } tctx, cancel := context.WithTimeout(ctx, defaultOpTimeout) @@ -49,22 +49,22 @@ func NewClient(ctx context.Context, hc *http.Client, release Release) (*Client, // RepoMD returns a alas.RepoMD containing sha256 information of a repositories contents func (c *Client) RepoMD(ctx context.Context) (alas.RepoMD, error) { - ctx = zlog.ContextWithValues(ctx, "component", "aws/Client.RepoMD") + log := c.log for _, mirror := range c.mirrors { m := *mirror m.Path = path.Join(m.Path, repoDataPath) - ctx := zlog.ContextWithValues(ctx, "mirror", m.String()) + log := log.With("mirror", m.String()) req, err := http.NewRequestWithContext(ctx, http.MethodGet, m.String(), nil) if err != nil { - zlog.Error(ctx).Err(err).Msg("failed to make request object") + log.ErrorContext(ctx, "failed to make request object", "reason", err) continue } - zlog.Debug(ctx).Msg("attempting repomd download") + log.DebugContext(ctx, "attempting repomd download") resp, err := c.c.Do(req) if err != nil { - zlog.Error(ctx).Err(err).Msg("failed to retrieve repomd") + log.ErrorContext(ctx, "failed to retrieve repomd", "reason", err) continue } defer resp.Body.Close() @@ -73,10 +73,9 @@ func (c *Client) RepoMD(ctx context.Context) (alas.RepoMD, error) { case http.StatusOK: // break default: - zlog.Error(ctx). - Int("code", resp.StatusCode). - Str("status", resp.Status). - Msg("unexpected HTTP response") + log.ErrorContext(ctx, "unexpected HTTP response", + "code", resp.StatusCode, + "status", resp.Status) continue } @@ -84,51 +83,49 @@ func (c *Client) RepoMD(ctx context.Context) (alas.RepoMD, error) { dec := xml.NewDecoder(resp.Body) dec.CharsetReader = xmlutil.CharsetReader if err := dec.Decode(&repoMD); err != nil { - zlog.Error(ctx). - Err(err). - Msg("failed xml unmarshal") + log.ErrorContext(ctx, "failed xml unmarshal", "reason", err) continue } - zlog.Debug(ctx).Msg("success") + log.DebugContext(ctx, "success") return repoMD, nil } - zlog.Error(ctx).Msg("exhausted all mirrors") + log.ErrorContext(ctx, "exhausted all mirrors") return alas.RepoMD{}, fmt.Errorf("all mirrors failed to retrieve repo metadata") } // Updates returns the *http.Response of the first mirror to establish a connection func (c *Client) Updates(ctx context.Context) (io.ReadCloser, error) { - ctx = zlog.ContextWithValues(ctx, "component", "aws/Client.Updates") + log := c.log for _, mirror := range c.mirrors { m := *mirror m.Path = path.Join(m.Path, updatesPath) - ctx := zlog.ContextWithValues(ctx, "mirror", m.String()) + log := log.With("mirror", m.String()) req, err := http.NewRequestWithContext(ctx, http.MethodGet, m.String(), nil) if err != nil { - zlog.Error(ctx).Err(err).Msg("failed to make request object") + log.ErrorContext(ctx, "failed to make request object", "reason", err) continue } tf, err := tmp.NewFile("", "") if err != nil { - zlog.Error(ctx).Err(err).Msg("failed to open temp file") + log.ErrorContext(ctx, "failed to open temp file", "reason", err) continue } var success bool defer func() { if !success { if err := tf.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + log.WarnContext(ctx, "unable to close spool", "reason", err) } } }() resp, err := c.c.Do(req) if err != nil { - zlog.Error(ctx).Err(err).Msg("failed to retrieve updates") + log.ErrorContext(ctx, "failed to retrieve updates", "reason", err) continue } defer resp.Body.Close() @@ -137,10 +134,9 @@ func (c *Client) Updates(ctx context.Context) (io.ReadCloser, error) { case http.StatusOK: // break default: - zlog.Error(ctx). - Int("code", resp.StatusCode). - Str("status", resp.Status). - Msg("unexpected HTTP response") + log.ErrorContext(ctx, "unexpected HTTP response", + "code", resp.StatusCode, + "status", resp.Status) continue } @@ -155,7 +151,7 @@ func (c *Client) Updates(ctx context.Context) (io.ReadCloser, error) { return nil, fmt.Errorf("failed to create gzip reader: %v", err) } - zlog.Debug(ctx).Msg("success") + log.DebugContext(ctx, "success") success = true return &gzippedFile{ Reader: gz, @@ -163,7 +159,7 @@ func (c *Client) Updates(ctx context.Context) (io.ReadCloser, error) { }, nil } - zlog.Error(ctx).Msg("exhausted all mirrors") + log.ErrorContext(ctx, "exhausted all mirrors") return nil, fmt.Errorf("all update_info mirrors failed to return a response") } @@ -176,7 +172,7 @@ type gzippedFile struct { } func (c *Client) getMirrors(ctx context.Context, list string) error { - ctx = zlog.ContextWithValues(ctx, "component", "aws/Client.getMirrors") + log := c.log req, err := http.NewRequestWithContext(ctx, http.MethodGet, list, nil) if err != nil { @@ -215,7 +211,6 @@ func (c *Client) getMirrors(ctx context.Context, list string) error { c.mirrors = append(c.mirrors, uu) } - zlog.Debug(ctx). - Msg("successfully got list of mirrors") + log.DebugContext(ctx, "successfully got list of mirrors") return nil } diff --git a/aws/client_test.go b/aws/client_test.go index b5f83a4a4..d1106ca31 100644 --- a/aws/client_test.go +++ b/aws/client_test.go @@ -2,13 +2,14 @@ package aws import ( "context" + "log/slog" "net/http" "net/http/httptest" "net/url" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) type clientTestcase struct { @@ -31,11 +32,12 @@ func (tc *clientTestcase) Run(ctx context.Context) func(*testing.T) { })) client := Client{ c: srv.Client(), + log: slog.Default(), mirrors: make([]*url.URL, 0), } return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) t.Cleanup(srv.Close) err := client.getMirrors(ctx, srv.URL) @@ -48,8 +50,9 @@ func (tc *clientTestcase) Run(ctx context.Context) func(*testing.T) { } } } + func TestClientGetMirrors(t *testing.T) { - ctx := context.Background() + ctx := test.Logging(t) tests := []clientTestcase{ { Release: AmazonLinux1, diff --git a/aws/distributionscanner.go b/aws/distributionscanner.go index ca4ac7fef..bd3fd0b19 100644 --- a/aws/distributionscanner.go +++ b/aws/distributionscanner.go @@ -3,11 +3,10 @@ package aws import ( "bytes" "context" + "log/slog" "regexp" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -71,17 +70,12 @@ func (*DistributionScanner) Kind() string { return scannerKind } // If the files are found but all regexp fail to match an empty slice is returned. func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "aws_dist_scanner", - "name", ds.Name(), - "version", ds.Version(), - "kind", ds.Kind(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + log := slog.With("layer", l.Hash.String(), "version", ds.Version()) + log.DebugContext(ctx, "start") + defer log.DebugContext(ctx, "done") files, err := l.Files(osReleasePath) if err != nil { - zlog.Debug(ctx).Msg("didn't find an os-release") + log.DebugContext(ctx, "didn't find an os-release") return nil, nil } for _, buff := range files { diff --git a/aws/updater.go b/aws/updater.go index 16a550ab1..7a3c895a9 100644 --- a/aws/updater.go +++ b/aws/updater.go @@ -9,8 +9,6 @@ import ( "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/aws/internal/alas" "github.com/quay/claircore/internal/xmlutil" @@ -43,7 +41,6 @@ func (u *Updater) Configure(ctx context.Context, _ driver.ConfigUnmarshaler, c * } func (u *Updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "aws/Updater.Fetch") client, err := NewClient(ctx, u.c, u.release) if err != nil { return nil, "", fmt.Errorf("failed to create client: %v", err) diff --git a/datastore/postgres/affected_manifests_e2e_test.go b/datastore/postgres/affected_manifests_e2e_test.go index f56aa4180..72c347721 100644 --- a/datastore/postgres/affected_manifests_e2e_test.go +++ b/datastore/postgres/affected_manifests_e2e_test.go @@ -8,11 +8,11 @@ import ( "testing" "github.com/jackc/pgx/v5/pgxpool" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/pkg/omnimatcher" + "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" pgtest "github.com/quay/claircore/test/postgres" ) @@ -27,7 +27,7 @@ type affectedE2E struct { func TestAffectedE2E(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) pool := pgtest.TestIndexerDB(ctx, t) store := NewIndexerStore(pool) @@ -161,7 +161,7 @@ func (e *affectedE2E) Run(t *testing.T) { // this is required so foreign key constraints do not // fail in later tests. func (e *affectedE2E) IndexArtifacts(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) const ( insertManifest = ` INSERT INTO manifest @@ -255,7 +255,7 @@ func (e *affectedE2E) IndexArtifacts(t *testing.T) { // IndexManifest confirms the contents of a manifest // can be written to the manifest index table. func (e *affectedE2E) IndexManifest(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) err := e.store.IndexManifest(ctx, &e.ir) if err != nil { t.Fatalf("failed to index manifest: %v", err) @@ -266,7 +266,7 @@ func (e *affectedE2E) IndexManifest(t *testing.T) { // in the vulnereability report reports the associated // manifest is affected. func (e *affectedE2E) AffectedManifests(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) om := omnimatcher.New(nil) for _, vuln := range e.vr.Vulnerabilities { hashes, err := e.store.AffectedManifests(ctx, *vuln, om.Vulnerable) diff --git a/datastore/postgres/affectedmanifest.go b/datastore/postgres/affectedmanifest.go index 16448f63b..2bc51152e 100644 --- a/datastore/postgres/affectedmanifest.go +++ b/datastore/postgres/affectedmanifest.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log/slog" "strconv" "time" @@ -12,7 +13,6 @@ import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore" ) @@ -107,7 +107,6 @@ WHERE ); ` ) - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/affectedManifests") // confirm the incoming vuln can be // resolved into a prototype index record @@ -160,7 +159,7 @@ WHERE pkg.ID = idStr pkgsToFilter = append(pkgsToFilter, pkg) } - zlog.Debug(ctx).Int("count", len(pkgsToFilter)).Msg("packages to filter") + slog.DebugContext(ctx, "packages to filter", "count", len(pkgsToFilter)) if err := rows.Err(); err != nil { return nil, fmt.Errorf("error scanning packages: %w", err) } @@ -183,7 +182,7 @@ WHERE }) } } - zlog.Debug(ctx).Int("count", len(filteredRecords)).Msg("vulnerable index records") + slog.DebugContext(ctx, "vulnerable index records", "count", len(filteredRecords)) // Query the manifest index for manifests containing the vulnerable // IndexRecords and create a set containing each unique manifest. @@ -232,7 +231,7 @@ WHERE return nil, err } } - zlog.Debug(ctx).Int("count", len(out)).Msg("affected manifests") + slog.DebugContext(ctx, "affected manifests", "count", len(out)) return out, nil } @@ -262,7 +261,6 @@ func protoRecord(ctx context.Context, pool *pgxpool.Pool, v claircore.Vulnerabil ` timeout = 5 * time.Second ) - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/protoRecord") protoRecord := claircore.IndexRecord{} // fill dist into prototype index record if exists @@ -302,7 +300,7 @@ func protoRecord(ctx context.Context, pool *pgxpool.Pool, v claircore.Vulnerabil VersionCodeName: v.Dist.VersionCodeName, VersionID: v.Dist.VersionID, } - zlog.Debug(ctx).Str("id", id).Msg("discovered distribution id") + slog.DebugContext(ctx, "discovered distribution id", "id", id) } } @@ -332,7 +330,7 @@ func protoRecord(ctx context.Context, pool *pgxpool.Pool, v claircore.Vulnerabil Name: v.Repo.Name, URI: v.Repo.URI, } - zlog.Debug(ctx).Str("id", id).Msg("discovered repo id") + slog.DebugContext(ctx, "discovered repo id", "id", id) } } diff --git a/datastore/postgres/connect.go b/datastore/postgres/connect.go index e9f0938c5..5a586664d 100644 --- a/datastore/postgres/connect.go +++ b/datastore/postgres/connect.go @@ -3,10 +3,10 @@ package postgres import ( "context" "fmt" + "log/slog" "github.com/jackc/pgx/v5/pgxpool" "github.com/prometheus/client_golang/prometheus" - "github.com/quay/zlog" "github.com/quay/claircore/datastore/postgres/types" "github.com/quay/claircore/pkg/poolstats" @@ -33,7 +33,7 @@ func Connect(ctx context.Context, connString string, applicationName string) (*p } if err := prometheus.Register(poolstats.NewCollector(pool, applicationName)); err != nil { - zlog.Info(ctx).Msg("pool metrics already registered") + slog.InfoContext(ctx, "pool metrics already registered") } return pool, nil diff --git a/datastore/postgres/deletemanifests.go b/datastore/postgres/deletemanifests.go index fd10616a5..1545f7b29 100644 --- a/datastore/postgres/deletemanifests.go +++ b/datastore/postgres/deletemanifests.go @@ -4,11 +4,11 @@ import ( "context" "errors" "fmt" + "log/slog" "github.com/jackc/pgx/v5" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/internal/dblock" @@ -43,7 +43,6 @@ var errLockFail = errors.New("lock failed") // The returned slice indicates the successfully deleted manifests. An error is // reported if none were able to be deleted. func (s *IndexerStore) DeleteManifests(ctx context.Context, ds ...claircore.Digest) ([]claircore.Digest, error) { - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/DeleteManifests") const ( getManifestID = `SELECT id FROM manifest WHERE hash = $1` getLayers = `SELECT layer_id FROM manifest_layer WHERE manifest_id = $1;` @@ -135,10 +134,9 @@ func (s *IndexerStore) DeleteManifests(ctx context.Context, ds ...claircore.Dige return fmt.Errorf("unable check layer usage: %w", err) } ra := tag.RowsAffected() - zlog.Debug(ctx). - Int64("count", ra). - Str("manifest", d.String()). - Msg("deleted layers for manifest") + slog.DebugContext(ctx, "deleted layers for manifest", + "count", ra, + "manifest", d) } deletedManifests = append(deletedManifests, d) return nil @@ -146,25 +144,20 @@ func (s *IndexerStore) DeleteManifests(ctx context.Context, ds ...claircore.Dige switch { case attemptErr == nil: case errors.Is(attemptErr, errLockFail): - zlog.Debug(ctx). - Stringer("manifest", d). - Msg("unable to obtain lock") + slog.DebugContext(ctx, "unable to obtain lock", "manifest", d) default: errs = append(errs, fmt.Errorf("%s: %w", d, attemptErr)) } } - zlog.Debug(ctx). - Int("count", len(deletedManifests)). - Int("nonexistant", len(ds)-len(deletedManifests)). - Msg("deleted manifests") + slog.DebugContext(ctx, "deleted manifests", + "count", len(deletedManifests), + "nonexistant", len(ds)-len(deletedManifests)) if len(deletedManifests) == 0 { err = errors.Join(errs...) return nil, err } if len(errs) > 0 { - zlog.Warn(ctx). - Errs("reason", errs). - Msg("unexpected errors") + slog.WarnContext(ctx, "unexpected errors", "reason", errs) } return deletedManifests, nil } diff --git a/datastore/postgres/deletemanifests_test.go b/datastore/postgres/deletemanifests_test.go index 51d29be92..f01a7083f 100644 --- a/datastore/postgres/deletemanifests_test.go +++ b/datastore/postgres/deletemanifests_test.go @@ -1,11 +1,9 @@ package postgres import ( - "context" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -17,13 +15,13 @@ import ( func TestDeleteManifests(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) pool := pgtest.TestIndexerDB(ctx, t) store := NewIndexerStore(pool) defer store.Close(ctx) t.Run("Nonexistent", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) in := []claircore.Digest{ test.RandomSHA256Digest(t), } @@ -36,7 +34,7 @@ func TestDeleteManifests(t *testing.T) { } }) t.Run("NonexistentMulti", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) in := []claircore.Digest{ test.RandomSHA256Digest(t), test.RandomSHA256Digest(t), @@ -54,7 +52,7 @@ func TestDeleteManifests(t *testing.T) { }) const insertManifest = `INSERT INTO manifest (hash) SELECT unnest($1::TEXT[]);` t.Run("One", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) want := []claircore.Digest{ test.RandomSHA256Digest(t), } @@ -70,7 +68,7 @@ func TestDeleteManifests(t *testing.T) { } }) t.Run("Locked", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) want := []claircore.Digest{ test.RandomSHA256Digest(t), test.RandomSHA256Digest(t), @@ -107,7 +105,7 @@ func TestDeleteManifests(t *testing.T) { } }) t.Run("Subset", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) in := make([]claircore.Digest, 8) for i := range in { in[i] = test.RandomSHA256Digest(t) @@ -139,7 +137,7 @@ INSERT INTO manifest_layer (i, manifest_id, layer_id) nManifests = 8 layersPer = 4 ) - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) ms := make([]claircore.Digest, nManifests) for i := range ms { ms[i] = test.RandomSHA256Digest(t) @@ -207,7 +205,7 @@ INSERT INTO manifest_layer (i, manifest_id, layer_id) nManifests = 8 nonBaseLayersPer = 3 ) - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) ms := make([]claircore.Digest, nManifests) for i := range ms { ms[i] = test.RandomSHA256Digest(t) @@ -289,7 +287,7 @@ INSERT INTO manifest_layer (i, manifest_id, layer_id) packageN = 10 ) s := NewIndexerStore(pool) - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) toDelete := make([]claircore.Digest, manifestsN) for i := range manifestsN { ir := &claircore.IndexReport{} diff --git a/datastore/postgres/enrichment.go b/datastore/postgres/enrichment.go index b3b6dd7d7..0d7edb6ef 100644 --- a/datastore/postgres/enrichment.go +++ b/datastore/postgres/enrichment.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log/slog" "sort" "strconv" "time" @@ -15,7 +16,6 @@ import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore/datastore" "github.com/quay/claircore/libvuln/driver" @@ -70,7 +70,6 @@ var ( ) func (s *MatcherStore) UpdateEnrichmentsIter(ctx context.Context, updater string, fp driver.Fingerprint, it datastore.EnrichmentIter) (uuid.UUID, error) { - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/MatcherStore.UpdateEnrichmentsIter") return s.updateEnrichments(ctx, updater, fp, it) } @@ -78,7 +77,6 @@ func (s *MatcherStore) UpdateEnrichmentsIter(ctx context.Context, updater string // EnrichmentRecord(s), and ensures enrichments from previous updates are not // queried by clients. func (s *MatcherStore) UpdateEnrichments(ctx context.Context, updater string, fp driver.Fingerprint, es []driver.EnrichmentRecord) (uuid.UUID, error) { - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/MatcherStore.UpdateEnrichments") enIter := func(yield func(record *driver.EnrichmentRecord, err error) bool) { for i := range es { if !yield(&es[i], nil) { @@ -133,7 +131,6 @@ DO NOTHING;` refreshView = `REFRESH MATERIALIZED VIEW CONCURRENTLY latest_update_operations;` ) - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/UpdateEnrichments") var id uint64 var ref uuid.UUID @@ -146,9 +143,7 @@ DO } updateEnrichmentsCounter.WithLabelValues("create").Add(1) updateEnrichmentsDuration.WithLabelValues("create").Observe(time.Since(start).Seconds()) - zlog.Debug(ctx). - Str("ref", ref.String()). - Msg("update_operation created") + slog.DebugContext(ctx, "update_operation created", "ref", ref) return nil }) if err != nil { @@ -180,7 +175,9 @@ DO // Periodically refresh planner statistics during bulk inserts to avoid stalls if enCt%analyzeEveryNRecords == 0 { if _, analyzeErr := s.pool.Exec(ctx, "ANALYZE enrichment"); analyzeErr != nil { - zlog.Warn(ctx).Err(analyzeErr).Int("record_count", enCt).Msg("failed to analyze enrichment table during processing") + slog.WarnContext(ctx, "failed to analyze enrichment table during processing", + "record_count", enCt, + "reason", analyzeErr) } } @@ -213,10 +210,9 @@ DO if _, err = s.pool.Exec(ctx, refreshView); err != nil { return uuid.Nil, fmt.Errorf("could not refresh latest_update_operations: %w", err) } - zlog.Debug(ctx). - Stringer("ref", ref). - Int("inserted", enCt). - Msg("update_operation committed") + slog.DebugContext(ctx, "update_operation committed", + "ref", ref, + "inserted", enCt) return ref, nil } @@ -256,7 +252,6 @@ where and l.kind = 'enrichment' limit 1;` - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/GetEnrichment") timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) { getEnrichmentsDuration.WithLabelValues("query", strconv.FormatBool(errors.Is(err, nil))).Observe(v) })) diff --git a/datastore/postgres/gc.go b/datastore/postgres/gc.go index 756203ffd..3bdd9f50d 100644 --- a/datastore/postgres/gc.go +++ b/datastore/postgres/gc.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log/slog" "runtime" "strings" "time" @@ -12,7 +13,6 @@ import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "golang.org/x/sync/semaphore" "github.com/quay/claircore/libvuln/driver" @@ -55,8 +55,6 @@ const ( // If a full GC is required run this method until the returned int64 value // is 0. func (s *MatcherStore) GC(ctx context.Context, keep int) (int64, error) { - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/GC") - // obtain update operations which need deletin' ops, totalOps, err := eligibleUpdateOpts(ctx, s.pool, keep) if err != nil { @@ -94,7 +92,7 @@ func (s *MatcherStore) GC(ctx context.Context, keep int) (int64, error) { case driver.EnrichmentKind: cleanup = enrichmentCleanup default: - zlog.Error(ctx).Str("kind", string(kind)).Msg("unknown updater kind; skipping cleanup") + slog.ErrorContext(ctx, "unknown updater kind; skipping cleanup", "kind", string(kind)) continue } for _, u := range us { @@ -229,15 +227,13 @@ AND v1.id = v2.id; ) start := time.Now() - ctx = zlog.ContextWithValues(ctx, "updater", updater) - zlog.Debug(ctx). - Msg("starting vuln clean up") + slog.DebugContext(ctx, "starting vuln clean up") res, err := pool.Exec(ctx, deleteOrphanedVulns, updater) if err != nil { gcCounter.WithLabelValues("deleteVulns", "false").Inc() return fmt.Errorf("failed while exec'ing vuln delete: %w", err) } - zlog.Debug(ctx).Int64("rows affected", res.RowsAffected()).Msg("vulns deleted") + slog.DebugContext(ctx, "vulns deleted", "rows affected", res.RowsAffected()) gcCounter.WithLabelValues("deleteVulns", "true").Inc() gcDuration.WithLabelValues("deleteVulns").Observe(time.Since(start).Seconds()) @@ -258,15 +254,13 @@ DELETE FROM enrichment e1 USING ) start := time.Now() - ctx = zlog.ContextWithValues(ctx, "updater", updater) - zlog.Debug(ctx). - Msg("starting enrichment clean up") + slog.DebugContext(ctx, "starting enrichment clean up") res, err := pool.Exec(ctx, deleteOrphanedEnrichments, updater) if err != nil { gcCounter.WithLabelValues("deleteEnrichments", "false").Inc() return fmt.Errorf("failed while exec'ing enrichment delete: %w", err) } - zlog.Debug(ctx).Int64("rows affected", res.RowsAffected()).Msg("enrichments deleted") + slog.DebugContext(ctx, "enrichments deleted", "rows affected", res.RowsAffected()) gcCounter.WithLabelValues("deleteEnrichments", "true").Inc() gcDuration.WithLabelValues("deleteEnrichments").Observe(time.Since(start).Seconds()) diff --git a/datastore/postgres/gc_test.go b/datastore/postgres/gc_test.go index b95538688..d00013cb0 100644 --- a/datastore/postgres/gc_test.go +++ b/datastore/postgres/gc_test.go @@ -9,8 +9,6 @@ import ( "net/http" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" "github.com/quay/claircore/libvuln/updates" @@ -146,7 +144,7 @@ func TestGC(t *testing.T) { for _, tt := range table { t.Run(tt.name, func(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) pool := pgtest.TestMatcherDB(ctx, t) store := NewMatcherStore(pool) locks, err := ctxlock.New(ctx, pool) diff --git a/datastore/postgres/get.go b/datastore/postgres/get.go index 0d732c10f..5ca8c7eaf 100644 --- a/datastore/postgres/get.go +++ b/datastore/postgres/get.go @@ -3,13 +3,13 @@ package postgres import ( "context" "fmt" + "log/slog" "strconv" "time" "github.com/jackc/pgx/v5" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/datastore" @@ -43,7 +43,6 @@ type recordQuery struct { // Get implements vulnstore.Vulnerability. func (s *MatcherStore) Get(ctx context.Context, records []*claircore.IndexRecord, opts datastore.GetOpts) (map[string][]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/Get") tx, err := s.pool.Begin(ctx) if err != nil { return nil, err @@ -57,10 +56,9 @@ func (s *MatcherStore) Get(ctx context.Context, records []*claircore.IndexRecord query, err := buildGetQuery(record, &opts) if err != nil { // if we cannot build a query for an individual record continue to the next - zlog.Debug(ctx). - Err(err). - Str("record", fmt.Sprintf("%+v", record)). - Msg("could not build query for record") + slog.DebugContext(ctx, "could not build query for record", + "reason", err, + "record", record) continue } rqs = append(rqs, &recordQuery{query: query, record: record}) diff --git a/datastore/postgres/getupdateoperationdiff_test.go b/datastore/postgres/getupdateoperationdiff_test.go index f377875e4..51f914461 100644 --- a/datastore/postgres/getupdateoperationdiff_test.go +++ b/datastore/postgres/getupdateoperationdiff_test.go @@ -1,15 +1,14 @@ package postgres import ( - "context" "fmt" "testing" "github.com/google/uuid" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" pgtest "github.com/quay/claircore/test/postgres" ) @@ -26,7 +25,7 @@ type diffTestCase struct { // are captured there, e.g. if there's no difference between the two operations. func TestGetUpdateDiff(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) cases := []diffTestCase{ // second op adds two new vulns diff --git a/datastore/postgres/getupdateoperations.go b/datastore/postgres/getupdateoperations.go index a808661e3..a71b9444d 100644 --- a/datastore/postgres/getupdateoperations.go +++ b/datastore/postgres/getupdateoperations.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log/slog" "time" "github.com/google/uuid" @@ -11,7 +12,6 @@ import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore/libvuln/driver" ) @@ -80,7 +80,6 @@ func (s *MatcherStore) GetLatestUpdateRef(ctx context.Context, kind driver.Updat queryEnrichment = `SELECT ref FROM update_operation WHERE kind = 'enrichment' ORDER BY id USING > LIMIT 1;` queryVulnerability = `SELECT ref FROM update_operation WHERE kind = 'vulnerability' ORDER BY id USING > LIMIT 1;` ) - ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/getLatestRef") var q string var label string @@ -156,15 +155,12 @@ func (s *MatcherStore) GetLatestUpdateRefs(ctx context.Context, kind driver.Upda } ret[uo.Updater] = ops } - zlog.Debug(ctx). - Int("count", len(ret)). - Msg("found updaters") + slog.DebugContext(ctx, "found updaters", "count", len(ret)) return ret, nil } func getLatestRefs(ctx context.Context, pool *pgxpool.Pool) (map[string][]driver.UpdateOperation, error) { const query = `SELECT DISTINCT ON (updater) updater, ref, fingerprint, date FROM update_operation ORDER BY updater, id USING >;` - ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/getLatestRefs") start := time.Now() @@ -195,9 +191,7 @@ func getLatestRefs(ctx context.Context, pool *pgxpool.Pool) (map[string][]driver } ret[uo.Updater] = ops } - zlog.Debug(ctx). - Int("count", len(ret)). - Msg("found updaters") + slog.DebugContext(ctx, "found updaters", "count", len(ret)) return ret, nil } @@ -208,7 +202,6 @@ func (s *MatcherStore) GetUpdateOperations(ctx context.Context, kind driver.Upda queryEnrichment = `SELECT ref, updater, fingerprint, date FROM update_operation WHERE updater = ANY($1) AND kind = 'enrichment' ORDER BY id DESC;` getUpdaters = `SELECT DISTINCT(updater) FROM update_operation;` ) - ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/getUpdateOperations") tx, err := s.pool.Begin(ctx) if err != nil { diff --git a/datastore/postgres/index_e2e_test.go b/datastore/postgres/index_e2e_test.go index 62e267805..d85f2cc6c 100644 --- a/datastore/postgres/index_e2e_test.go +++ b/datastore/postgres/index_e2e_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -26,9 +25,11 @@ type mockScnr struct { func (m mockScnr) Name() string { return m.name } + func (m mockScnr) Kind() string { return m.kind } + func (m mockScnr) Version() string { return m.version } @@ -220,7 +221,7 @@ func (e *indexE2e) Run(t *testing.T) { // Manifest and Layer identities so layer code // foreign key references do not fail. func (e *indexE2e) PersistManifest(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) err := e.store.PersistManifest(ctx, e.manifest) if err != nil { t.Fatalf("failed to persist manifest: %v", err) @@ -230,7 +231,7 @@ func (e *indexE2e) PersistManifest(t *testing.T) { // RegisterScanner confirms a scanner can be registered // and provides this scanner for other subtests to use func (e *indexE2e) RegisterScanner(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) err := e.store.RegisterScanners(ctx, e.scnrs) if err != nil { t.Fatalf("failed to register scnr: %v", err) @@ -241,7 +242,7 @@ func (e *indexE2e) RegisterScanner(t *testing.T) { // selecting packages associated with a layer works // correctly. func (e *indexE2e) IndexAndRetrievePackages(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) A := test.GenUniquePackages(e.packageGen) for _, scnr := range e.scnrs { @@ -265,7 +266,7 @@ func (e *indexE2e) IndexAndRetrievePackages(t *testing.T) { // selecting distributions associated with a layer works // correctly. func (e *indexE2e) IndexAndRetrieveDistributions(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) A := test.GenUniqueDistributions(e.distGen) for _, scnr := range e.scnrs { @@ -289,7 +290,7 @@ func (e *indexE2e) IndexAndRetrieveDistributions(t *testing.T) { // selecting repositories associated with a layer works // correctly. func (e *indexE2e) IndexAndRetrieveRepos(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) A := test.GenUniqueRepositories(e.repoGen) for _, scnr := range e.scnrs { @@ -312,7 +313,7 @@ func (e *indexE2e) IndexAndRetrieveRepos(t *testing.T) { // LayerScanned confirms the book keeping involved in marking a layer // scanned works correctly. func (e *indexE2e) LayerScanned(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) for _, scnr := range e.scnrs { err := e.store.SetLayerScanned(ctx, e.manifest.Layers[0].Hash, scnr) if err != nil { @@ -332,7 +333,7 @@ func (e *indexE2e) LayerScanned(t *testing.T) { // LayerScannedNotExists confirms an error is returned when attempting // to obtain if a layer was scanned by a non-existent scanner. func (e *indexE2e) LayerScannedNotExists(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) scnr := mockScnr{ name: "invalid", kind: "invalid", @@ -348,7 +349,7 @@ func (e *indexE2e) LayerScannedNotExists(t *testing.T) { // LayerScannedFalse confirms a false boolean is returned when attempting // to obtain if a non-existent layer was scanned by a valid scanner func (e *indexE2e) LayerScannedFalse(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) // create a layer that has not been persisted to the store layer := &claircore.Layer{ @@ -367,7 +368,7 @@ func (e *indexE2e) LayerScannedFalse(t *testing.T) { // IndexReport confirms the book keeping around index reports works // correctly. func (e *indexE2e) IndexReport(t *testing.T) { - ctx := zlog.Test(e.ctx, t) + ctx := test.Logging(t, e.ctx) A := &claircore.IndexReport{ Hash: e.manifest.Hash, diff --git a/datastore/postgres/indexmanifest.go b/datastore/postgres/indexmanifest.go index 014cd4c4b..cc905576a 100644 --- a/datastore/postgres/indexmanifest.go +++ b/datastore/postgres/indexmanifest.go @@ -3,13 +3,13 @@ package postgres import ( "context" "fmt" + "log/slog" "strconv" "time" "github.com/jackc/pgx/v5" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore" ) @@ -50,7 +50,6 @@ func (s *IndexerStore) IndexManifest(ctx context.Context, ir *claircore.IndexRep ON CONFLICT DO NOTHING; ` ) - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/IndexerStore.IndexManifest") if ir.Hash.String() == "" { return fmt.Errorf("received empty hash; cannot associate contents with a manifest hash") @@ -59,7 +58,7 @@ func (s *IndexerStore) IndexManifest(ctx context.Context, ir *claircore.IndexRep records := ir.IndexRecords() if len(records) == 0 { - zlog.Warn(ctx).Msg("manifest being indexed has 0 index records") + slog.WarnContext(ctx, "manifest being indexed has 0 index records") return nil } diff --git a/datastore/postgres/indexpackage.go b/datastore/postgres/indexpackage.go index eef3fe9ae..ee970fc01 100644 --- a/datastore/postgres/indexpackage.go +++ b/datastore/postgres/indexpackage.go @@ -4,12 +4,12 @@ import ( "cmp" "context" "fmt" + "log/slog" "time" "github.com/jackc/pgx/v5" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -99,8 +99,6 @@ func (s *IndexerStore) IndexPackages(ctx context.Context, pkgs []*claircore.Pack ` ) - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/IndexerStore.IndexPackages") - var batch, assocBatch pgx.Batch skipCt := 0 queueInsert := func(pkg *claircore.Package) { @@ -155,19 +153,17 @@ func (s *IndexerStore) IndexPackages(ctx context.Context, pkgs []*claircore.Pack if err != nil { return err } - zlog.Debug(ctx). - Int("skipped", skipCt). - Int("inserted", len(pkgs)-skipCt). - Msg("packages inserted") + slog.DebugContext(ctx, "packages inserted", + "skipped", skipCt, + "inserted", len(pkgs)-skipCt) start = time.Now() err = tx.SendBatch(ctx, &assocBatch).Close() indexPackageCounter.WithLabelValues("insertWith_batch").Add(1) indexPackageDuration.WithLabelValues("insertWith_batch").Observe(time.Since(start).Seconds()) - zlog.Debug(ctx). - Int("skipped", skipCt). - Int("inserted", len(pkgs)-skipCt). - Msg("scanartifacts inserted") + slog.DebugContext(ctx, "scanartifacts inserted", + "skipped", skipCt, + "inserted", len(pkgs)-skipCt) if err != nil { return err } diff --git a/datastore/postgres/indexpackage_benchmark_test.go b/datastore/postgres/indexpackage_benchmark_test.go index 19bbdd57a..8578a8619 100644 --- a/datastore/postgres/indexpackage_benchmark_test.go +++ b/datastore/postgres/indexpackage_benchmark_test.go @@ -1,11 +1,8 @@ package postgres import ( - "context" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" @@ -14,7 +11,6 @@ import ( func Benchmark_IndexPackages(b *testing.B) { integration.NeedDB(b) - ctx := context.Background() benchmarks := []struct { // the name of this benchmark name string @@ -179,7 +175,7 @@ func Benchmark_IndexPackages(b *testing.B) { for _, bench := range benchmarks { b.Run(bench.name, func(b *testing.B) { - ctx := zlog.Test(ctx, b) + ctx := test.Logging(b) pool := pgtest.TestIndexerDB(ctx, b) store := NewIndexerStore(pool) @@ -215,5 +211,4 @@ func Benchmark_IndexPackages(b *testing.B) { } }) } - } diff --git a/datastore/postgres/matcher_store.go b/datastore/postgres/matcher_store.go index 2f980cf43..218b01049 100644 --- a/datastore/postgres/matcher_store.go +++ b/datastore/postgres/matcher_store.go @@ -8,7 +8,6 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/stdlib" - "github.com/quay/zlog" "github.com/remind101/migrate" "github.com/quay/claircore/datastore" @@ -56,7 +55,6 @@ var ( // DeleteUpdateOperations implements vulnstore.Updater. func (s *MatcherStore) DeleteUpdateOperations(ctx context.Context, id ...uuid.UUID) (int64, error) { const query = `DELETE FROM update_operation WHERE ref = ANY($1::uuid[]);` - ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/deleteUpdateOperations") if len(id) == 0 { return 0, nil } diff --git a/datastore/postgres/packagesbylayer_benchmark_test.go b/datastore/postgres/packagesbylayer_benchmark_test.go index 2818aae30..1fa9d75de 100644 --- a/datastore/postgres/packagesbylayer_benchmark_test.go +++ b/datastore/postgres/packagesbylayer_benchmark_test.go @@ -1,11 +1,8 @@ package postgres import ( - "context" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" @@ -14,7 +11,6 @@ import ( func Benchmark_PackagesByLayer(b *testing.B) { integration.NeedDB(b) - ctx := context.Background() benchmarks := []struct { name string hash claircore.Digest @@ -91,7 +87,7 @@ func Benchmark_PackagesByLayer(b *testing.B) { for _, bench := range benchmarks { b.Run(bench.name, func(b *testing.B) { - ctx := zlog.Test(ctx, b) + ctx := test.Logging(b) pool := pgtest.TestIndexerDB(ctx, b) store := NewIndexerStore(pool) diff --git a/datastore/postgres/querybuilder_test.go b/datastore/postgres/querybuilder_test.go index fefee94f2..fd2d4036e 100644 --- a/datastore/postgres/querybuilder_test.go +++ b/datastore/postgres/querybuilder_test.go @@ -1,14 +1,12 @@ package postgres import ( - "context" "strings" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/datastore" @@ -33,7 +31,7 @@ func TestGetQueryBuilderDeterministicArgs(t *testing.T) { both = `(((("package_name" = 'package-0') AND ("package_kind" = 'binary')) OR (("package_name" = 'source-package-0') AND ("package_kind" = 'source'))) AND ` noSource = `((("package_name" = 'package-0') AND ("package_kind" = 'binary')) AND ` ) - var table = []struct { + table := []struct { // name of test name string // the expected query string returned @@ -253,7 +251,7 @@ type testCase struct { // considered when querying for vulns func TestLatestVulns(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) cases := []testCase{ { diff --git a/datastore/postgres/recordupdatetime.go b/datastore/postgres/recordupdatetime.go index fff4a298b..71e7d4aa5 100644 --- a/datastore/postgres/recordupdatetime.go +++ b/datastore/postgres/recordupdatetime.go @@ -3,10 +3,10 @@ package postgres import ( "context" "fmt" + "log/slog" "time" "github.com/jackc/pgx/v5/pgxpool" - "github.com/quay/zlog" "github.com/quay/claircore/libvuln/driver" ) @@ -57,9 +57,7 @@ func recordUpdaterStatus(ctx context.Context, pool *pgxpool.Pool, updaterName st last_error = $4 RETURNING updater_name;` ) - - ctx = zlog.ContextWithValues(ctx, - "component", "internal/vulnstore/postgres/recordUpdaterStatus") + log := slog.With("updater", updaterName) tx, err := pool.Begin(ctx) if err != nil { @@ -70,17 +68,13 @@ func recordUpdaterStatus(ctx context.Context, pool *pgxpool.Pool, updaterName st var returnedUpdaterName string if updaterError == nil { - zlog.Debug(ctx). - Str("updater", updaterName). - Msg("recording successful update") + log.DebugContext(ctx, "recording successful update") _, err := tx.Exec(ctx, upsertSuccessfulUpdate, updaterName, updateTime, fingerprint) if err != nil { return fmt.Errorf("failed to upsert successful updater status: %w", err) } } else { - zlog.Debug(ctx). - Str("updater", updaterName). - Msg("recording failed update") + log.DebugContext(ctx, "recording failed update") if err := tx.QueryRow(ctx, upsertFailedUpdate, updaterName, updateTime, fingerprint, updaterError.Error()).Scan(&returnedUpdaterName); err != nil { return fmt.Errorf("failed to upsert failed updater status: %w", err) } @@ -89,10 +83,7 @@ func recordUpdaterStatus(ctx context.Context, pool *pgxpool.Pool, updaterName st if err := tx.Commit(ctx); err != nil { return fmt.Errorf("failed to commit transaction: %w", err) } - - zlog.Debug(ctx). - Str("updater", updaterName). - Msg("updater status stored in database") + log.DebugContext(ctx, "updater status stored in database") return nil } @@ -109,9 +100,6 @@ func recordUpdaterSetStatus(ctx context.Context, pool *pgxpool.Pool, updaterSet WHERE updater_name like $2 || '%';` ) - ctx = zlog.ContextWithValues(ctx, - "component", "internal/vulnstore/postgres/recordUpdaterSetStatus") - tx, err := pool.Begin(ctx) if err != nil { return fmt.Errorf("unable to start transaction: %w", err) @@ -127,10 +115,9 @@ func recordUpdaterSetStatus(ctx context.Context, pool *pgxpool.Pool, updaterSet return fmt.Errorf("failed to commit transaction: %w", err) } - zlog.Debug(ctx). - Str("factory", updaterSet). - Int64("rowsAffected", tag.RowsAffected()). - Msg("status updated for factory updaters") + slog.DebugContext(ctx, "status updated for factory updaters", + "factory", updaterSet, + "rowsAffected", tag.RowsAffected()) return nil } diff --git a/datastore/postgres/setlayerscanned.go b/datastore/postgres/setlayerscanned.go index ec97d59ae..39f8842aa 100644 --- a/datastore/postgres/setlayerscanned.go +++ b/datastore/postgres/setlayerscanned.go @@ -7,7 +7,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -36,7 +35,6 @@ var ( ) func (s *IndexerStore) SetLayerScanned(ctx context.Context, hash claircore.Digest, vs indexer.VersionedScanner) error { - ctx = zlog.ContextWithValues(ctx, "scanner", vs.Name()) const query = ` WITH scanner diff --git a/datastore/postgres/update_e2e_test.go b/datastore/postgres/update_e2e_test.go index 0d05562b2..367afa8d9 100644 --- a/datastore/postgres/update_e2e_test.go +++ b/datastore/postgres/update_e2e_test.go @@ -14,7 +14,6 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgxpool" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/datastore" @@ -27,7 +26,7 @@ import ( // TestUpdateE2E performs an end to end test of update operations and diffing func TestUpdateE2E(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := t.Context() cases := []updateE2e{ { @@ -84,7 +83,7 @@ func (e *updateE2e) Run(ctx context.Context) func(*testing.T) { {"DeleteUpdateOperations", e.DeleteUpdateOperations}, } return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) pool := pgtest.TestMatcherDB(ctx, t) e.pool = pool e.s = NewMatcherStore(pool) @@ -118,7 +117,7 @@ var updateOpCmp = cmpopts.IgnoreFields(driver.UpdateOperation{}, "Date") func (e *updateE2e) Update(ctx context.Context) func(*testing.T) { fp := driver.Fingerprint(uuid.New().String()) return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) e.updateOps = make([]driver.UpdateOperation, 0, e.Updates) for _, vs := range e.vulns() { ref, err := e.s.UpdateVulnerabilities(ctx, e.updater, fp, vs) @@ -144,7 +143,7 @@ func (e *updateE2e) Update(ctx context.Context) func(*testing.T) { // operation returns the expected results. func (e *updateE2e) GetUpdateOperations(ctx context.Context) func(*testing.T) { return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) out, err := e.s.GetUpdateOperations(ctx, driver.VulnerabilityKind, e.updater) if err != nil { t.Fatalf("failed to get UpdateOperations: %v", err) @@ -179,7 +178,7 @@ type update struct { // and then an update to an whole updater set func (e *updateE2e) recordUpdaterStatus(ctx context.Context) func(*testing.T) { return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) errorText := "test error" firstUpdateDate := time.Date(2020, time.Month(1), 22, 2, 10, 30, 0, time.UTC) secondUpdateDate := time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC) @@ -256,7 +255,7 @@ func orNoIndex(a int) string { // independently calculated diffs. func (e *updateE2e) Diff(ctx context.Context) func(t *testing.T) { return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) for n := range e.vulns() { // This does a bunch of checks so that the first operation is // compared appropriately. @@ -344,7 +343,7 @@ func (e *updateE2e) DeleteUpdateOperations(ctx context.Context) func(*testing.T) assocExists = `SELECT EXISTS(SELECT 1 FROM uo_vuln JOIN update_operation uo ON (uo_vuln.uo = uo.id) WHERE uo.ref = $1::uuid);` ) var exists bool - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) for _, op := range e.updateOps { _, err := e.s.DeleteUpdateOperations(ctx, op.Ref) if err != nil { diff --git a/datastore/postgres/updatevulnerabilities.go b/datastore/postgres/updatevulnerabilities.go index 5b58f9383..de8d148b2 100644 --- a/datastore/postgres/updatevulnerabilities.go +++ b/datastore/postgres/updatevulnerabilities.go @@ -5,6 +5,7 @@ import ( "context" "crypto/md5" "fmt" + "log/slog" "strconv" "strings" "time" @@ -13,7 +14,6 @@ import ( "github.com/jackc/pgx/v5" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/datastore" @@ -48,7 +48,6 @@ var ( // UpdateVulnerabilitiesIter implements vulnstore.Updater. func (s *MatcherStore) UpdateVulnerabilitiesIter(ctx context.Context, updater string, fp driver.Fingerprint, it datastore.VulnerabilityIter) (uuid.UUID, error) { - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/MatcherStore.UpdateVulnerabilitiesIter") return s.updateVulnerabilities(ctx, updater, fp, it, nil) } @@ -58,7 +57,6 @@ func (s *MatcherStore) UpdateVulnerabilitiesIter(ctx context.Context, updater st // provided vulnerabilities and computes a diff comprising the removed // and added vulnerabilities for this UpdateOperation. func (s *MatcherStore) UpdateVulnerabilities(ctx context.Context, updater string, fp driver.Fingerprint, vulns []*claircore.Vulnerability) (uuid.UUID, error) { - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/MatcherStore.UpdateVulnerabilities") iterVulns := func(yield func(*claircore.Vulnerability, error) bool) { for i := range vulns { if !yield(vulns[i], nil) { @@ -81,7 +79,6 @@ func (s *MatcherStore) UpdateVulnerabilities(ctx context.Context, updater string // - Insert the new vulnerabilities // - Associate new vulnerabilities with new updateOperation func (s *MatcherStore) DeltaUpdateVulnerabilities(ctx context.Context, updater string, fingerprint driver.Fingerprint, vulns []*claircore.Vulnerability, deletedVulns []string) (uuid.UUID, error) { - ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/MatcherStore.DeltaUpdateVulnerabilities") iterVulns := func(yield func(*claircore.Vulnerability, error) bool) { for i := range vulns { if !yield(vulns[i], nil) { @@ -171,12 +168,11 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string updateVulnerabilitiesCounter.WithLabelValues("create", strconv.FormatBool(delta)).Add(1) updateVulnerabilitiesDuration.WithLabelValues("create", strconv.FormatBool(delta)).Observe(time.Since(start).Seconds()) - zlog.Debug(ctx). - Str("ref", ref.String()). - Msg("update_operation created") + log := slog.With("ref", ref) + log.DebugContext(ctx, "update_operation created") if delta { - ctx = zlog.ContextWithValues(ctx, "mode", "delta") + log = log.With("mode", "delta") // Get existing vulns // The reason this still works even though the new update_operation // is already created is because the latest_update_operation view isn't updated until @@ -312,11 +308,9 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string return uuid.Nil, fmt.Errorf("could not refresh latest_update_operations: %w", err) } - zlog.Debug(ctx). - Str("ref", ref.String()). - Int("skipped", skipCt). - Int("inserted", vulnCt-skipCt). - Msg("update_operation committed") + log.DebugContext(ctx, "update_operation committed", + "skipped", skipCt, + "inserted", vulnCt-skipCt) return ref, nil } diff --git a/datastore/postgres/updatevulnerabilities_test.go b/datastore/postgres/updatevulnerabilities_test.go index 69f218b90..09b23906d 100644 --- a/datastore/postgres/updatevulnerabilities_test.go +++ b/datastore/postgres/updatevulnerabilities_test.go @@ -1,15 +1,14 @@ package postgres import ( - "context" "testing" "github.com/google/uuid" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/datastore" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" pgtest "github.com/quay/claircore/test/postgres" ) @@ -29,7 +28,7 @@ type op struct { func TestGetLatestVulnerabilities(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) cases := []latestVulnTestCase{ { @@ -297,6 +296,7 @@ func TestGetLatestVulnerabilities(t *testing.T) { // run test cases for _, tc := range cases { t.Run(tc.TestName, func(t *testing.T) { + ctx := test.Logging(t, ctx) _, err := store.DeltaUpdateVulnerabilities(ctx, tc.Updater, driver.Fingerprint(uuid.New().String()), tc.FirstOp.vulns, tc.FirstOp.deletedVulns) if err != nil { t.Fatalf("failed to perform update for first op: %v", err) diff --git a/debian/distributionscanner.go b/debian/distributionscanner.go index 72f4bbb57..f2f643947 100644 --- a/debian/distributionscanner.go +++ b/debian/distributionscanner.go @@ -5,14 +5,13 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "regexp" "runtime/trace" "strconv" "strings" "unicode" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/osrelease" @@ -39,18 +38,15 @@ func (*DistributionScanner) Kind() string { return "distribution" } // Scan implements [indexer.DistributionScanner]. func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "debian/DistributionScanner.Scan", - "version", ds.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + log := slog.With("version", ds.Version(), "layer", l.Hash.String()) + log.DebugContext(ctx, "start") + defer log.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { return nil, fmt.Errorf("debian: unable to open layer: %w", err) } - d, err := findDist(ctx, sys) + d, err := findDist(ctx, log, sys) if err != nil { return nil, err } @@ -60,20 +56,19 @@ func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([] return []*claircore.Distribution{d}, nil } -func findDist(ctx context.Context, sys fs.FS) (*claircore.Distribution, error) { +func findDist(ctx context.Context, log *slog.Logger, sys fs.FS) (*claircore.Distribution, error) { f, err := sys.Open(osrelease.Path) switch { case errors.Is(err, nil): case errors.Is(err, fs.ErrNotExist): - zlog.Debug(ctx).Msg("no os-release file") + log.DebugContext(ctx, "no os-release file") return nil, nil default: return nil, fmt.Errorf("debian: unexpected error: %w", err) } kv, err := osrelease.Parse(ctx, f) if err != nil { - zlog.Info(ctx). - Err(err).Msg("malformed os-release file") + log.InfoContext(ctx, "malformed os-release file", "reason", err) return nil, nil } if kv[`ID`] != `debian` { @@ -89,14 +84,12 @@ func findDist(ctx context.Context, sys fs.FS) (*claircore.Distribution, error) { name = strings.TrimFunc(ver.FindString(kv[`VERSION`]), func(r rune) bool { return !unicode.IsLetter(r) }) } if name == "" || idstr == "" { - zlog.Info(ctx). - Err(err).Msg("malformed os-release file") + log.InfoContext(ctx, "malformed os-release file", "reason", err) return nil, nil } id, err := strconv.ParseInt(idstr, 10, 32) if err != nil { - zlog.Info(ctx). - Err(err).Msg("malformed os-release file") + log.InfoContext(ctx, "malformed os-release file", "reason", err) return nil, nil } return mkDist(name, int(id)), nil diff --git a/debian/distributionscanner_test.go b/debian/distributionscanner_test.go index 5a2241da4..afcdde75e 100644 --- a/debian/distributionscanner_test.go +++ b/debian/distributionscanner_test.go @@ -1,19 +1,18 @@ package debian import ( - "context" "io/fs" + "log/slog" "os" "path/filepath" "regexp" "testing" - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) func TestDistributionScanner(t *testing.T) { ver := regexp.MustCompile(`^\d+ \(\w+\)$`) - ctx := zlog.Test(context.Background(), t) ents, err := os.ReadDir(`testdata/dist`) if err != nil { t.Fatal(err) @@ -31,8 +30,9 @@ func TestDistributionScanner(t *testing.T) { for tcDir, tcEnts := range testCase { for _, e := range tcEnts { t.Run(e.Name(), func(t *testing.T) { + ctx := test.Logging(t) sys := os.DirFS(filepath.Join(tcDir, e.Name())) - d, err := findDist(ctx, sys) + d, err := findDist(ctx, slog.Default(), sys) if err != nil { t.Error(err) } diff --git a/debian/matcher_integration_test.go b/debian/matcher_integration_test.go index fdcae16d1..7b157cb04 100644 --- a/debian/matcher_integration_test.go +++ b/debian/matcher_integration_test.go @@ -1,7 +1,6 @@ package debian import ( - "context" "encoding/json" "fmt" "net/http" @@ -12,14 +11,13 @@ import ( "path/filepath" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/datastore/postgres" "github.com/quay/claircore/internal/matcher" "github.com/quay/claircore/libvuln/driver" "github.com/quay/claircore/libvuln/updates" "github.com/quay/claircore/pkg/ctxlock/v2" + "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" pgtest "github.com/quay/claircore/test/postgres" ) @@ -37,7 +35,7 @@ func TestMain(m *testing.M) { // CVE data func TestMatcherIntegration(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) pool := pgtest.TestMatcherDB(ctx, t) store := postgres.NewMatcherStore(pool) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/debian/parser.go b/debian/parser.go index e9f6f0952..f1e6b03db 100644 --- a/debian/parser.go +++ b/debian/parser.go @@ -5,8 +5,7 @@ import ( "encoding/json" "fmt" "io" - - "github.com/quay/zlog" + "log/slog" "github.com/quay/claircore" ) @@ -34,8 +33,7 @@ type ReleaseData struct { // Parse implements [driver.Parser]. func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "debian/Updater.Parse") - zlog.Info(ctx).Msg("starting parse") + slog.InfoContext(ctx, "starting parse") defer r.Close() var vulnsJSON JSONData diff --git a/debian/updater.go b/debian/updater.go index 7522c3515..81ea48a39 100644 --- a/debian/updater.go +++ b/debian/updater.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "net/http" "net/textproto" "net/url" @@ -15,8 +16,6 @@ import ( "strconv" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" "github.com/quay/claircore/pkg/tmp" ) @@ -184,28 +183,25 @@ Listing: dist = strings.Trim(dist, "/") rf, err := dir.Parse(path.Join(dist, `Release`)) if err != nil { - zlog.Info(ctx). - Err(err). - Stringer("context", dir). - Str("target", path.Join(dist, `Release`)). - Msg("unable to construct URL") + slog.InfoContext(ctx, "unable to construct URL", + "reason", err, + "context", dir, + "target", path.Join(dist, `Release`)) continue } req, err := http.NewRequestWithContext(ctx, http.MethodGet, rf.String(), nil) if err != nil { - zlog.Info(ctx). - Err(err). - Stringer("url", rf). - Msg("unable to construct request") + slog.InfoContext(ctx, "unable to construct request", + "reason", err, + "url", rf) continue } req.Header.Set("range", "bytes=0-512") res, err := f.c.Do(req) if err != nil { - zlog.Info(ctx). - Err(err). - Stringer("url", rf). - Msg("unable to do request") + slog.InfoContext(ctx, "unable to do request", + "reason", err, + "url", rf) continue } buf.Reset() @@ -216,31 +212,31 @@ Listing: case http.StatusNotFound: // Probably extremely old, it's fine. continue default: - zlog.Info(ctx). - Str("status", res.Status). - Stringer("url", rf). - Msg("unexpected response") + slog.InfoContext(ctx, "unexpected response", + "status", res.Status, + "url", rf) continue } tp := textproto.NewReader(bufio.NewReader(io.MultiReader(&buf, bytes.NewReader([]byte("\r\n\r\n"))))) h, err := tp.ReadMIMEHeader() if err != nil { - zlog.Info(ctx).Err(err).Msg("unable to read MIME-ish headers") + slog.InfoContext(ctx, "unable to read MIME-ish headers", + "reason", err) continue } sv := h.Get("Version") if sv == "" { - zlog.Debug(ctx).Str("dist", dist).Msg("no version assigned, skipping") + slog.DebugContext(ctx, "no version assigned, skipping", "dist", dist) continue } vs := strings.Split(sv, ".") if len(vs) == 1 { - zlog.Debug(ctx).Str("dist", dist).Msg("no version assigned, skipping") + slog.DebugContext(ctx, "no version assigned, skipping", "dist", dist) continue } ver, err := strconv.ParseInt(vs[0], 10, 32) if err != nil { - zlog.Info(ctx).Err(err).Msg("unable to parse version") + slog.InfoContext(ctx, "unable to parse version", "reason", err) continue } @@ -275,7 +271,6 @@ func (u *updater) Name() string { // Configure implements [driver.Configurable]. func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, "component", "debian/Updater.Configure") u.c = c var cfg UpdaterConfig if err := f(&cfg); err != nil { @@ -283,14 +278,13 @@ func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c * } if cfg.DistsURL != "" || cfg.OVALURL != "" { - zlog.Error(ctx).Msg("configured with deprecated URLs") + slog.ErrorContext(ctx, "configured with deprecated URLs") return fmt.Errorf("debian: neither url nor dists_url should be used anymore; use json_url and dists_urls instead") } if cfg.JSONURL != "" { u.jsonURL = cfg.JSONURL - zlog.Info(ctx). - Msg("configured JSON database URL") + slog.InfoContext(ctx, "configured JSON database URL") } return nil @@ -298,9 +292,7 @@ func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c * // Fetch implements [driver.Fetcher]. func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "debian/Updater.Fetch", - "database", u.jsonURL) + log := slog.With("database", u.jsonURL) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.jsonURL, nil) if err != nil { @@ -324,7 +316,7 @@ func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io switch resp.StatusCode { case http.StatusOK: if fingerprint == "" || fp != string(fingerprint) { - zlog.Info(ctx).Msg("fetching latest JSON database") + log.InfoContext(ctx, "fetching latest JSON database") break } fallthrough @@ -343,7 +335,7 @@ func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io defer func() { if !success { if err := f.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + log.WarnContext(ctx, "unable to close spool", "reason", err) } } }() @@ -353,7 +345,7 @@ func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io if _, err := f.Seek(0, io.SeekStart); err != nil { return nil, "", fmt.Errorf("failed to seek body: %w", err) } - zlog.Info(ctx).Msg("fetched latest json database successfully") + log.InfoContext(ctx, "fetched latest json database successfully") success = true return f, driver.Fingerprint(fp), err diff --git a/docs/contributor/logging.md b/docs/contributor/logging.md index d43495175..91c21e772 100644 --- a/docs/contributor/logging.md +++ b/docs/contributor/logging.md @@ -1,7 +1,5 @@ # Logging -All the logging in claircore is done with [zerolog][doc] via `context.Context` -values. The `zlog` package takes OpenTelemetry labels and attaches them to -`zerolog` events. +All the logging in claircore is done with [`log/slog`][doc]. This allows for claircore's logging to be used consistently throughout all the packages without having unintended prints to stderr. @@ -9,20 +7,28 @@ packages without having unintended prints to stderr. ## How to Log ### Adding Context -In a function, use `zlog` to add key-value pairs of any relevant context: + +Within a function, create a `*slog.Logger` to add key-value pairs of any +relevant context: ```go {{#include ../logger_test.go:kvs}} ``` -Alternatively, the `go.opentelemetry.io/otel/baggage` package can be used for -more explicit control around the baggage values. +Alternatively, the `github.com/quay/claircore/toolkit/log` package has a helper +for associating multiple `slog.Attr` values with a `context.Context`. +```go +{{#include ../logger_test.go:ctx}} +``` + +Programs using claircore should configure their `slog.Handler` to extract the +values using the key in `github.com/quay/claircore/toolkit/log` or use the +`Wrap` helper. ### Logging style #### Constant Messages -Zerolog emits lines when the `Msg` or `Msgf` methods are called. Project style -is to _not_ use `Msgf`. Any variable data should be set as key-value pairs on -the Event object. +Project style is to use string constants for all logging calls. Any variable +data should be passed as additional arguments to the `slog` methods. For example, don't do this: ```go @@ -66,14 +72,6 @@ times in the logs. Claircore attempts to have consistent leveled logging. The rules for figuring out what level to use is: -* Panic - - There's some occurrence that means the process won't work correctly. - -* Fatal - - Unused, because it prevents defers from running. - * Error Something unexpected occurred and the process can continue, but a @@ -96,4 +94,11 @@ out what level to use is: and exiting functions, stepping through a function, or specific file paths used while work is being done. -[doc]: https://pkg.go.dev/github.com/rs/zerolog@v1.26.0 +In exceptional situations, levels of `slog.LevelDebug-4` or `slog.LevelError+4` +may be used for "Trace" and "Emergency" logs. There are no predefined constants +for these. + +#### Contexts +All logging calls should use the "Context" variant whenever possible. + +[doc]: https://pkg.go.dev/log/slog diff --git a/docs/logger_test.go b/docs/logger_test.go index 47abe5f01..5dc34c3e3 100644 --- a/docs/logger_test.go +++ b/docs/logger_test.go @@ -2,26 +2,35 @@ package docs_test import ( "context" + "fmt" + "log/slog" "time" - "github.com/quay/zlog" + "github.com/quay/claircore/toolkit/log" ) // Example_logger is an example annotated for inclusion in the prose // documentation. func Example_logger() { ctx := context.Background() - // ANCHOR: kvs - ctx = zlog.ContextWithValues(ctx, - "component", "Example.Logger") - // ANCHOR_END: kvs + { + // ANCHOR: kvs + log := slog.With("contextual", "value") + log.DebugContext(ctx, "message") + // ANCHOR_END: kvs + } + + { + // ANCHOR: ctx + ctx := log.With(ctx, "contextual", "value") + slog.DebugContext(ctx, "message") + // ANCHOR_END: ctx + } // ANCHOR: bad_example - zlog.Info(ctx).Msgf("done at: %v", time.Now()) + slog.InfoContext(ctx, fmt.Sprintf("done at: %v", time.Now())) // ANCHOR_END: bad_example // ANCHOR: good_example - zlog.Info(ctx). - Time("time", time.Now()). - Msgf("done") + slog.InfoContext(ctx, "done", "time", time.Now()) // ANCHOR_END: good_example } diff --git a/dpkg/distroless_scanner.go b/dpkg/distroless_scanner.go index 3abfa4063..261692781 100644 --- a/dpkg/distroless_scanner.go +++ b/dpkg/distroless_scanner.go @@ -7,12 +7,11 @@ import ( "fmt" "io" "io/fs" + "log/slog" "net/textproto" "path/filepath" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -55,12 +54,8 @@ func (ps *DistrolessScanner) Kind() string { return distrolessKind } func (ps *DistrolessScanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore.Package, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "dpkg/DistrolessScanner.Scan", - "version", ps.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := layer.FS() if err != nil { @@ -73,7 +68,7 @@ func (ps *DistrolessScanner) Scan(ctx context.Context, layer *claircore.Layer) ( return err } if d.Name() == "status.d" && d.IsDir() { - zlog.Debug(ctx).Str("path", p).Msg("found potential distroless dpkg db directory") + slog.DebugContext(ctx, "found potential distroless dpkg db directory", "path", p) dbFiles, err := fs.ReadDir(sys, p) if err != nil { return fmt.Errorf("error reading DB directory: %w", err) @@ -81,8 +76,8 @@ func (ps *DistrolessScanner) Scan(ctx context.Context, layer *claircore.Layer) ( for _, f := range dbFiles { pkgCt := 0 fn := filepath.Join(p, f.Name()) - ctx = zlog.ContextWithValues(ctx, "database-file", fn) - zlog.Debug(ctx).Msg("examining package database") + log := slog.With("database-file", fn) + log.DebugContext(ctx, "examining package database") db, err := sys.Open(fn) if err != nil { return fmt.Errorf("reading database files from layer failed: %w", err) @@ -124,14 +119,12 @@ func (ps *DistrolessScanner) Scan(ctx context.Context, layer *claircore.Layer) ( case errors.Is(err, io.EOF): default: if _, ok := err.(textproto.ProtocolError); ok { - zlog.Warn(ctx).Err(err).Msg("unable to read DB entry") + log.WarnContext(ctx, "unable to read DB entry", "reason", err) goto Restart } - zlog.Warn(ctx).Err(err).Msg("error reading DB file") + log.WarnContext(ctx, "error reading DB file", "reason", err) } - zlog.Debug(ctx). - Int("count", pkgCt). - Msg("found packages") + slog.DebugContext(ctx, "found packages", "count", pkgCt) } } return nil diff --git a/dpkg/distroless_scanner_test.go b/dpkg/distroless_scanner_test.go index 37451c06c..c6ad7e00e 100644 --- a/dpkg/distroless_scanner_test.go +++ b/dpkg/distroless_scanner_test.go @@ -1,18 +1,16 @@ package dpkg import ( - "context" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" ) func TestDistrolessLayer(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) want := []*claircore.Package{ { Name: "base-files", diff --git a/dpkg/scanner.go b/dpkg/scanner.go index 505e2057b..99f5b5020 100644 --- a/dpkg/scanner.go +++ b/dpkg/scanner.go @@ -10,14 +10,13 @@ import ( "fmt" "io" "io/fs" + "log/slog" "net/textproto" "path/filepath" "runtime/trace" "slices" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -60,12 +59,8 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco // Preamble defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "dpkg/Scanner.Scan", - "version", ps.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := layer.FS() if err != nil { @@ -91,7 +86,7 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco if err := fs.WalkDir(sys, ".", walk); err != nil { return nil, err } - zlog.Debug(ctx).Msg("scanned for possible databases") + slog.DebugContext(ctx, "scanned for possible databases") // If we didn't find anything, this loop is completely skipped. var pkgs []*claircore.Package @@ -109,7 +104,7 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco switch { case err == nil: case errors.Is(err, errNotDpkgDB): - zlog.Info(ctx).AnErr("reason", err).Msg("skipping possible database") + slog.InfoContext(ctx, "skipping possible database", "reason", err) default: return nil, err } @@ -158,7 +153,7 @@ func sortpkg(a, b *claircore.Package) int { // // "Found"is used for scratch space and results are appended to the slice pointed to by "out". func loadDatabase(ctx context.Context, sys fs.FS, dir string, found *packages, out *[]*claircore.Package) error { - zlog.Debug(ctx).Msg("examining package database") + slog.DebugContext(ctx, "examining package database") // We want the "status" file. fn := filepath.Join(dir, "status") @@ -166,9 +161,7 @@ func loadDatabase(ctx context.Context, sys fs.FS, dir string, found *packages, o switch { case errors.Is(err, nil): case errors.Is(err, fs.ErrNotExist): - zlog.Debug(ctx). - Str("filename", fn). - Msg("false positive") + slog.DebugContext(ctx, "false positive", "filename", fn) return err default: return fmt.Errorf("reading status file from layer failed: %w", err) @@ -195,9 +188,7 @@ func loadDatabase(ctx context.Context, sys fs.FS, dir string, found *packages, o } p, ok := found.bin[k] if !ok { - zlog.Debug(ctx). - Str("package", k). - Msg("extra metadata found, ignoring") + slog.DebugContext(ctx, "extra metadata found, ignoring", "package", k) continue } f, err := sys.Open(n) @@ -208,17 +199,14 @@ func loadDatabase(ctx context.Context, sys fs.FS, dir string, found *packages, o _, err = io.Copy(hash, f) f.Close() if err != nil { - zlog.Warn(ctx). - Err(err). - Str("package", n). - Msg("unable to read package metadata") + slog.WarnContext(ctx, "unable to read package metadata", + "package", n, + "reason", err) continue } p.RepositoryHint = hex.EncodeToString(hash.Sum(nil)) } - zlog.Debug(ctx). - Int("count", len(found.bin)). - Msg("found packages") + slog.DebugContext(ctx, "found packages", "count", len(found.bin)) for _, pkg := range found.bin { *out = append(*out, pkg) @@ -322,7 +310,7 @@ Restart: switch { case errors.Is(err, io.EOF): default: - zlog.Warn(ctx).Err(err).Msg("unable to read entry") + slog.WarnContext(ctx, "unable to read entry", "reason", err) goto Restart } return nil diff --git a/dpkg/scanner_test.go b/dpkg/scanner_test.go index 7af0768b3..ec55e8418 100644 --- a/dpkg/scanner_test.go +++ b/dpkg/scanner_test.go @@ -3,7 +3,6 @@ package dpkg import ( "archive/tar" "bufio" - "context" "errors" "io" "net/textproto" @@ -12,7 +11,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" @@ -825,7 +823,7 @@ func TestScanner(t *testing.T) { }, } slices.SortFunc(want, sortpkg) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) l := test.RealizeLayer(ctx, t, test.LayerRef{ Registry: "docker.io", Name: "library/ubuntu", @@ -846,7 +844,7 @@ func TestExtraMetadata(t *testing.T) { t.Parallel() mod := test.Modtime(t, "scanner_test.go") layerfile := test.GenerateFixture(t, `extrametadata.layer`, mod, extraMetadataSetup) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) var l claircore.Layer var s Scanner @@ -964,7 +962,7 @@ func TestKeyringPackage(t *testing.T) { func TestParsedSource(t *testing.T) { t.Parallel() const filename = `testdata/postgresql.status` - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) db, err := os.Open(filename) if err != nil { @@ -998,7 +996,7 @@ func TestParsedSource(t *testing.T) { func TestNotDB(t *testing.T) { t.Parallel() const filename = `testdata/vcpkg.status` - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) db, err := os.Open(filename) if err != nil { diff --git a/enricher/cvss/cvss.go b/enricher/cvss/cvss.go index 5f032f1e6..d273c0d90 100644 --- a/enricher/cvss/cvss.go +++ b/enricher/cvss/cvss.go @@ -9,14 +9,13 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "sort" "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/enricher" "github.com/quay/claircore/libvuln/driver" @@ -110,8 +109,6 @@ func (*Enricher) Name() string { return name } // FetchEnrichment implements driver.EnrichmentUpdater. func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/cvss/Enricher/FetchEnrichment") - // year → sha256 prev := make(map[int]string) if err := json.Unmarshal([]byte(hint), &prev); err != nil && hint != "" { @@ -126,10 +123,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) if err != nil { return nil, hint, err } - zlog.Debug(ctx). - Int("year", y). - Stringer("url", u). - Msg("fetching meta file") + slog.DebugContext(ctx, "fetching meta file", "year", y, "url", u) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) if err != nil { return nil, hint, err @@ -148,20 +142,17 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) if err := mf.Parse(&buf); err != nil { return nil, hint, err } - zlog.Debug(ctx). - Int("year", y). - Stringer("url", u). - Time("mod", mf.LastModified). - Msg("parsed meta file") + slog.DebugContext(ctx, "parsed meta file", + "year", y, + "url", u, + "mod", mf.LastModified) cur[y] = strings.ToUpper(mf.SHA256) } doFetch := false for _, y := range yrs { if prev[y] != cur[y] { - zlog.Info(ctx). - Int("year", y). - Msg("change detected") + slog.InfoContext(ctx, "change detected", "year", y) doFetch = true break } @@ -178,7 +169,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) defer func() { if !success { if err := out.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + slog.WarnContext(ctx, "unable to close spool", "reason", err) } } }() @@ -195,10 +186,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) if err != nil { return nil, hint, fmt.Errorf("unable to create request: %w", err) } - zlog.Debug(ctx). - Int("year", y). - Stringer("url", u). - Msg("requesting json") + slog.DebugContext(ctx, "requesting json", "year", y, "url", u) res, err := e.c.Do(req) if err != nil { return nil, hint, fmt.Errorf("unable to do request: %w", err) @@ -232,7 +220,6 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) // ParseEnrichment implements driver.EnrichmentUpdater. func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]driver.EnrichmentRecord, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/cvss/Enricher/ParseEnrichment") // Our Fetch method actually has all the smarts w/r/t to constructing the // records, so this is just decoding in a loop. defer rc.Close() @@ -244,9 +231,7 @@ func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]dri ret = append(ret, driver.EnrichmentRecord{}) err = dec.Decode(&ret[len(ret)-1]) } - zlog.Debug(ctx). - Int("count", len(ret)). - Msg("decoded enrichments") + slog.DebugContext(ctx, "decoded enrichments", "count", len(ret)) if err != nil && !errors.Is(err, io.EOF) { return nil, err } @@ -255,8 +240,6 @@ func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]dri // Enrich implements driver.Enricher. func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *claircore.VulnerabilityReport) (string, []json.RawMessage, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/cvss/Enricher/Enrich") - // We return any CVSS blobs for CVEs mentioned in the free-form parts of the // vulnerability. m := make(map[string][]json.RawMessage) @@ -264,8 +247,7 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla erCache := make(map[string][]driver.EnrichmentRecord) for id, v := range r.Vulnerabilities { t := make(map[string]struct{}) - ctx := zlog.ContextWithValues(ctx, - "vuln", v.Name) + log := slog.With("vuln", v.Name) for _, elem := range []string{ v.Name, v.Links, @@ -281,9 +263,7 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla for m := range t { ts = append(ts, m) } - zlog.Debug(ctx). - Strs("cve", ts). - Msg("found CVEs") + log.DebugContext(ctx, "found CVEs", "cve", ts) sort.Strings(ts) cveKey := strings.Join(ts, "_") @@ -296,9 +276,7 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla } erCache[cveKey] = rec } - zlog.Debug(ctx). - Int("count", len(rec)). - Msg("found records") + log.DebugContext(ctx, "found records", "count", len(rec)) for _, r := range rec { m[id] = append(m[id], r.Enrichment) } diff --git a/enricher/cvss/cvss_test.go b/enricher/cvss/cvss_test.go index 47d2d8b10..e22bcb7fd 100644 --- a/enricher/cvss/cvss_test.go +++ b/enricher/cvss/cvss_test.go @@ -17,15 +17,15 @@ import ( "time" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" ) func TestConfigure(t *testing.T) { t.Parallel() - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) tt := []configTestcase{ { Name: "None", @@ -91,7 +91,7 @@ type configTestcase struct { func (tc configTestcase) Run(ctx context.Context) func(*testing.T) { e := &Enricher{} return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) f := tc.Config if f == nil { f = noopConfig @@ -111,7 +111,7 @@ func noopConfig(_ any) error { return nil } func TestFetch(t *testing.T) { t.Parallel() - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) srv := mockServer(t) tt := []fetchTestcase{ { @@ -175,7 +175,7 @@ type fetchTestcase struct { func (tc fetchTestcase) Run(ctx context.Context, srv *httptest.Server) func(*testing.T) { e := &Enricher{} return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f := func(i any) error { cfg, ok := i.(*Config) if !ok { @@ -234,7 +234,7 @@ func mockServer(t *testing.T) *httptest.Server { func TestParse(t *testing.T) { t.Parallel() - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) srv := mockServer(t) tt := []parseTestcase{ { @@ -254,7 +254,7 @@ type parseTestcase struct { func (tc parseTestcase) Run(ctx context.Context, srv *httptest.Server) func(*testing.T) { e := &Enricher{} return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) f := func(i any) error { cfg, ok := i.(*Config) if !ok { @@ -285,7 +285,7 @@ func (tc parseTestcase) Run(ctx context.Context, srv *httptest.Server) func(*tes func TestEnrich(t *testing.T) { t.Parallel() - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) feedIn, err := os.Open("testdata/feed.json") if err != nil { t.Fatal(err) diff --git a/enricher/cvss/feed.go b/enricher/cvss/feed.go index 5f61c870a..5a959fdbf 100644 --- a/enricher/cvss/feed.go +++ b/enricher/cvss/feed.go @@ -4,10 +4,9 @@ import ( "context" "encoding/json" "io" + "log/slog" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" ) @@ -59,7 +58,6 @@ func newItemFeed(year int, r io.Reader) (*itemFeed, error) { // entire serialization in memory. func (f *itemFeed) WriteCVSS(ctx context.Context, w io.Writer) error { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/cvss/itemFeed/WriteCVSS") // Use records directly because our parse step doesn't actually parse // anything -- the Fetch step rips out the relevant JSON. var skip, wrote uint @@ -104,10 +102,9 @@ func (f *itemFeed) WriteCVSS(ctx context.Context, w io.Writer) error { } wrote++ } - zlog.Debug(ctx). - Int("year", f.year). - Uint("skip", skip). - Uint("wrote", wrote). - Msg("wrote cvss items") + slog.DebugContext(ctx, "wrote cvss items", + "year", f.year, + "skip", skip, + "wrote", wrote) return nil } diff --git a/enricher/cvss/feed_test.go b/enricher/cvss/feed_test.go index cea9bc562..824c5b971 100644 --- a/enricher/cvss/feed_test.go +++ b/enricher/cvss/feed_test.go @@ -5,11 +5,11 @@ import ( "os" "testing" - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) func TestFeedIngest(t *testing.T) { - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) in, err := os.Open("testdata/feed.json") if err != nil { t.Fatal(err) diff --git a/enricher/epss/epss.go b/enricher/epss/epss.go index 8bbabd23c..6e32c84f5 100644 --- a/enricher/epss/epss.go +++ b/enricher/epss/epss.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "path" @@ -17,8 +18,6 @@ import ( "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/enricher" "github.com/quay/claircore/internal/httputil" @@ -76,7 +75,6 @@ func NewFactory() driver.UpdaterSetFactory { } func (e *Enricher) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/epss/Enricher/Configure") var cfg Config e.c = c e.feedPath = currentFeedURL() @@ -94,7 +92,7 @@ func (e *Enricher) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c // only .gz file is supported if strings.HasSuffix(*cfg.URL, ".gz") { - //overwrite feedPath is cfg provides another baseURL path + // overwrite feedPath is cfg provides another baseURL path e.feedPath = *cfg.URL } else { return fmt.Errorf("invalid baseURL root: expected a '.gz' file, but got '%q'", *cfg.URL) @@ -106,8 +104,6 @@ func (e *Enricher) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c // FetchEnrichment implements driver.EnrichmentUpdater. func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/epss/Enricher/FetchEnrichment") - out, err := tmp.NewFile("", "epss.") if err != nil { return nil, "", err @@ -116,7 +112,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F defer func() { if !success { if err := out.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + slog.WarnContext(ctx, "unable to close spool", "reason", err) } } }() @@ -140,7 +136,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F if etag := resp.Header.Get("etag"); etag != "" { newFingerprint = driver.Fingerprint(etag) if prevFingerprint == newFingerprint { - zlog.Info(ctx).Str("fingerprint", string(newFingerprint)).Msg("file unchanged; skipping processing") + slog.InfoContext(ctx, "file unchanged; skipping processing", "fingerprint", string(newFingerprint)) return nil, prevFingerprint, nil } newFingerprint = driver.Fingerprint(etag) @@ -207,7 +203,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F r, err := newItemFeed(record, modelVersion, date) if err != nil { - zlog.Warn(ctx).Err(err).Msg("skipping invalid record") + slog.WarnContext(ctx, "skipping invalid record", "reason", err) continue } @@ -217,7 +213,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F totalCVEs++ } - zlog.Info(ctx).Int("totalCVEs", totalCVEs).Msg("processed CVEs") + slog.InfoContext(ctx, "processed CVEs", "totalCVEs", totalCVEs) if _, err := out.Seek(0, io.SeekStart); err != nil { return nil, newFingerprint, fmt.Errorf("unable to reset file pointer: %w", err) } @@ -228,8 +224,6 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F // ParseEnrichment implements driver.EnrichmentUpdater. func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]driver.EnrichmentRecord, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/epss/Enricher/ParseEnrichment") - defer rc.Close() dec := json.NewDecoder(rc) @@ -244,9 +238,7 @@ func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]dri ret = append(ret, record) } - zlog.Debug(ctx). - Int("count", len(ret)). - Msg("decoded enrichments") + slog.DebugContext(ctx, "decoded enrichments", "count", len(ret)) if !errors.Is(err, io.EOF) { return nil, fmt.Errorf("error decoding enrichment records: %w", err) @@ -274,13 +266,12 @@ func currentFeedURL() string { } func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *claircore.VulnerabilityReport) (string, []json.RawMessage, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/epss/Enricher/Enrich") m := make(map[string][]json.RawMessage) erCache := make(map[string][]driver.EnrichmentRecord) for id, v := range r.Vulnerabilities { t := make(map[string]struct{}) - ctx := zlog.ContextWithValues(ctx, "vuln", v.Name) + log := slog.With("vuln", v.Name) for _, elem := range []string{ v.Name, @@ -288,13 +279,13 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla } { // Check if the element is non-empty before running the regex if elem == "" { - zlog.Debug(ctx).Str("element", elem).Msg("skipping empty element") + log.DebugContext(ctx, "skipping empty element", "element", elem) continue } matches := enricher.CVERegexp.FindAllString(elem, -1) if len(matches) == 0 { - zlog.Debug(ctx).Str("element", elem).Msg("no CVEs found in element") + log.DebugContext(ctx, "no CVEs found in element", "element", elem) continue } for _, m := range matches { @@ -304,7 +295,7 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla // Skip if no CVEs were found if len(t) == 0 { - zlog.Debug(ctx).Msg("no CVEs found in vulnerability metadata") + log.DebugContext(ctx, "no CVEs found in vulnerability metadata") continue } @@ -326,11 +317,11 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla erCache[cveKey] = rec } - zlog.Debug(ctx).Int("count", len(rec)).Msg("found records") + log.DebugContext(ctx, "found records", "count", len(rec)) // Skip if no enrichment records are found if len(rec) == 0 { - zlog.Debug(ctx).Strs("cve", ts).Msg("no enrichment records found for CVEs") + log.DebugContext(ctx, "no enrichment records found for CVEs", "cve", ts) continue } diff --git a/enricher/epss/epss_test.go b/enricher/epss/epss_test.go index d10810e58..d5d279827 100644 --- a/enricher/epss/epss_test.go +++ b/enricher/epss/epss_test.go @@ -16,15 +16,15 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" ) func TestConfigure(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) tt := []configTestcase{ { Name: "None", // No configuration provided, should use default @@ -96,7 +96,7 @@ func TestConfigure(t *testing.T) { func (tc configTestcase) Run(ctx context.Context) func(*testing.T) { e := &Enricher{} return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) f := tc.Config if f == nil { f = noopConfig @@ -114,7 +114,6 @@ func (tc configTestcase) Run(ctx context.Context) func(*testing.T) { func TestFetch(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) srv := mockServer(t) tt := []fetchTestcase{ @@ -143,6 +142,7 @@ func TestFetch(t *testing.T) { }, } + ctx := context.Background() for _, tc := range tt { t.Run(tc.Name, tc.Run(ctx, srv)) } @@ -201,7 +201,7 @@ func mockServer(t *testing.T) *httptest.Server { func (tc fetchTestcase) Run(ctx context.Context, srv *httptest.Server) func(*testing.T) { return func(t *testing.T) { e := &Enricher{} - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) configFunc := func(i any) error { cfg, ok := i.(*Config) if !ok { @@ -233,7 +233,7 @@ func (tc fetchTestcase) Run(ctx context.Context, srv *httptest.Server) func(*tes func TestParse(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) srv := mockServer(t) tt := []parseTestcase{ { @@ -253,7 +253,7 @@ type parseTestcase struct { func (tc parseTestcase) Run(ctx context.Context, srv *httptest.Server) func(*testing.T) { e := &Enricher{} return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) f := func(i any) error { cfg, ok := i.(*Config) if !ok { @@ -302,7 +302,7 @@ func (g *fakeGetter) GetEnrichment(ctx context.Context, cves []string) ([]driver func TestEnrich(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) srv := mockServer(t) e := &Enricher{} f := func(i any) error { diff --git a/enricher/kev/kev.go b/enricher/kev/kev.go index d7d4bce74..e8682b180 100644 --- a/enricher/kev/kev.go +++ b/enricher/kev/kev.go @@ -7,13 +7,12 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "net/http" "net/url" "slices" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/enricher" "github.com/quay/claircore/libvuln/driver" @@ -91,8 +90,6 @@ func (*Enricher) Name() string { return name } // FetchEnrichment implements driver.EnrichmentUpdater. func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/kev/Enricher.FetchEnrichment") - req, err := http.NewRequestWithContext(ctx, http.MethodGet, e.feed.String(), nil) if err != nil { return nil, hint, fmt.Errorf("kev: unable to create request: %w", err) @@ -116,12 +113,12 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) } fallthrough case http.StatusNotModified: - zlog.Info(ctx).Msg("database unchanged since last fetch") + slog.InfoContext(ctx, "database unchanged since last fetch") return nil, hint, driver.Unchanged default: return nil, hint, fmt.Errorf("http response error: %s %d", res.Status, res.StatusCode) } - zlog.Debug(ctx).Msg("successfully requested database") + slog.DebugContext(ctx, "successfully requested database") out, err := tmp.NewFile("", "kev.") if err != nil { @@ -131,7 +128,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) defer func() { if !success { if err := out.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + slog.WarnContext(ctx, "unable to close spool", "reason", err) } } }() @@ -149,17 +146,13 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, hint driver.Fingerprint) success = true hint = driver.Fingerprint(res.Header.Get("Last-Modified")) - zlog.Debug(ctx). - Str("hint", string(hint)). - Msg("using new hint") + slog.DebugContext(ctx, "using new hint", "hint", string(hint)) return out, hint, nil } // ParseEnrichment implements driver.EnrichmentUpdater. func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]driver.EnrichmentRecord, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/kev/Enricher.ParseEnrichment") - var root Root buf := bufio.NewReader(rc) if err := json.NewDecoder(buf).Decode(&root); err != nil { @@ -196,14 +189,12 @@ func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]dri // Enrich implements driver.Enricher. func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *claircore.VulnerabilityReport) (string, []json.RawMessage, error) { - ctx = zlog.ContextWithValues(ctx, "component", "enricher/kev/Enricher.Enrich") - m := make(map[string][]json.RawMessage) erCache := make(map[string][]driver.EnrichmentRecord) for id, v := range r.Vulnerabilities { t := make(map[string]struct{}) - ctx := zlog.ContextWithValues(ctx, "vuln", v.Name) + log := slog.With("vuln", v.Name) for _, elem := range []string{ v.Name, @@ -211,13 +202,13 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla } { // Check if the element is non-empty before running the regex if elem == "" { - zlog.Debug(ctx).Str("element", elem).Msg("skipping empty element") + log.DebugContext(ctx, "skipping empty element", "element", elem) continue } matches := enricher.CVERegexp.FindAllString(elem, -1) if len(matches) == 0 { - zlog.Debug(ctx).Str("element", elem).Msg("no CVEs found in element") + log.DebugContext(ctx, "no CVEs found in element", "element", elem) continue } for _, m := range matches { @@ -227,7 +218,7 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla // Skip if no CVEs were found if len(t) == 0 { - zlog.Debug(ctx).Msg("no CVEs found in vulnerability metadata") + log.DebugContext(ctx, "no CVEs found in vulnerability metadata") continue } @@ -249,11 +240,11 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla erCache[cveKey] = rec } - zlog.Debug(ctx).Int("count", len(rec)).Msg("found records") + log.DebugContext(ctx, "found records", "count", len(rec)) // Skip if no enrichment records are found if len(rec) == 0 { - zlog.Debug(ctx).Strs("cve", ts).Msg("no enrichment records found for CVEs") + log.DebugContext(ctx, "no enrichment records found for CVEs", "cve", ts) continue } diff --git a/enricher/kev/kev_test.go b/enricher/kev/kev_test.go index 7b3f5a5a9..9ae6e30b1 100644 --- a/enricher/kev/kev_test.go +++ b/enricher/kev/kev_test.go @@ -15,10 +15,10 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" ) // Define a static Last-Modified for testing purposes @@ -28,7 +28,6 @@ func noopConfig(_ any) error { return nil } func TestConfigure(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) type configTestcase struct { Config func(any) error @@ -87,7 +86,7 @@ func TestConfigure(t *testing.T) { for _, tc := range tt { t.Run(tc.Name, func(t *testing.T) { e := &Enricher{} - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f := tc.Config if f == nil { f = noopConfig @@ -156,7 +155,6 @@ func mockServer(t *testing.T) *httptest.Server { func TestFetch(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) srv := mockServer(t) type fetchTestcase struct { @@ -218,7 +216,7 @@ func TestFetch(t *testing.T) { for _, tc := range tt { t.Run(tc.Name, func(t *testing.T) { e := &Enricher{} - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) configFunc := func(i any) error { cfg, ok := i.(*Config) if !ok { @@ -251,7 +249,7 @@ func TestFetch(t *testing.T) { func TestParse(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) srv := mockServer(t) e := &Enricher{} @@ -336,7 +334,7 @@ func (g fakeGetter) GetEnrichment(_ context.Context, cves []string) ([]driver.En func TestEnrich(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) srv := mockServer(t) e := &Enricher{} diff --git a/go.mod b/go.mod index 6c2216b25..95b6258ea 100644 --- a/go.mod +++ b/go.mod @@ -20,9 +20,7 @@ require ( github.com/quay/claircore/toolkit v1.3.0 github.com/quay/claircore/updater/driver v1.0.0 github.com/quay/goval-parser v0.8.8 - github.com/quay/zlog v1.1.9 github.com/remind101/migrate v0.0.0-20170729031349-52c1edff7319 - github.com/rs/zerolog v1.32.0 github.com/spdx/tools-golang v0.5.6 github.com/ulikunitz/xz v0.5.15 go.opentelemetry.io/otel v1.39.0 @@ -53,7 +51,6 @@ require ( github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lib/pq v1.10.2 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect diff --git a/go.sum b/go.sum index 5e87f1eab..3498f4ec4 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,6 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -22,7 +21,6 @@ github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -67,10 +65,6 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= @@ -81,7 +75,6 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoXLtmE3I0PLs= github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= @@ -96,17 +89,12 @@ github.com/quay/claircore/toolkit v1.3.0 h1:QncygaArnuSKbkPESD2zMDz5xJLWlJxAGPZ6 github.com/quay/claircore/toolkit v1.3.0/go.mod h1:REVn3WdU+9yMurWa+h9mfuiPWYzKqSaKIGWZ4Xanj5g= github.com/quay/goval-parser v0.8.8 h1:Uf+f9iF2GIR5GPUY2pGoa9il2+4cdES44ZlM0mWm4cA= github.com/quay/goval-parser v0.8.8/go.mod h1:Y0NTNfPYOC7yxsYKzJOrscTWUPq1+QbtHw4XpPXWPMc= -github.com/quay/zlog v1.1.9 h1:O9/vfCUcGGUs0ukqQ77xPCJBPqpZBJ00jt7IUMsRco8= -github.com/quay/zlog v1.1.9/go.mod h1:O7OCW9oe7igrswhjKlyOvTo2+6FPsV7L0/owWEX6JHE= github.com/remind101/migrate v0.0.0-20170729031349-52c1edff7319 h1:ukjThsA2ou7AmovpwtMVkNQSuoN/v5U16+JomTz3c7o= github.com/remind101/migrate v0.0.0-20170729031349-52c1edff7319/go.mod h1:rhSvwcijY9wfmrBYrfCvapX8/xOTV46NAUjBRgUyJqc= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= -github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/spdx/tools-golang v0.5.6 h1:HUwSJWxyAR7vBstEeZ1+guD6Jcl4TVsKyTBUwT0RjTQ= github.com/spdx/tools-golang v0.5.6/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= @@ -153,9 +141,7 @@ golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/gobin/exe.go b/gobin/exe.go index 2b522846f..c746712b6 100644 --- a/gobin/exe.go +++ b/gobin/exe.go @@ -6,13 +6,12 @@ import ( "errors" "fmt" "io" + "log/slog" "regexp" "strconv" "strings" _ "unsafe" // for error linkname tricks - "github.com/quay/zlog" - "github.com/quay/claircore" ) @@ -31,21 +30,17 @@ func toPackages(ctx context.Context, out *[]*claircore.Package, p string, r io.R case errors.Is(err, errNotGoExe): return nil default: - zlog.Debug(ctx). - Err(err). - Msg("unable to open executable") + slog.DebugContext(ctx, "unable to open executable", "reason", err) return nil } - ctx = zlog.ContextWithValues(ctx, "exe", p) + log := slog.With("exe", p) pkgdb := "go:" + p badVers := make(map[string]string) defer func() { if len(badVers) == 0 { return } - zlog.Warn(ctx). - Interface("module_versions", badVers). - Msg("invalid semantic versions found in binary") + log.WarnContext(ctx, "invalid semantic versions found in binary", "module_versions", badVers) }() // TODO(hank) This package could use canonical versions, but the @@ -80,9 +75,10 @@ func toPackages(ctx context.Context, out *[]*claircore.Package, p string, r io.R NormalizedVersion: runtimeVer, }) - ev := zlog.Debug(ctx) - vs := map[string]string{ - "stdlib": bi.GoVersion, + debug := log.Enabled(ctx, slog.LevelDebug) + var attrs []slog.Attr + if debug { + attrs = append(attrs, slog.String("stdlib", bi.GoVersion)) } // The go main module version is reported differently depending on the go @@ -147,8 +143,8 @@ func toPackages(ctx context.Context, out *[]*claircore.Package, p string, r io.R NormalizedVersion: mainVer, }) - if ev.Enabled() { - vs[bi.Main.Path] = bi.Main.Version + if debug && bi.Main.Path != "" { + attrs = append(attrs, slog.String(bi.Main.Path, bi.Main.Version)) } for _, d := range bi.Deps { // Replacements are only evaluated for the main module and seem to only @@ -174,18 +170,18 @@ func toPackages(ctx context.Context, out *[]*claircore.Package, p string, r io.R NormalizedVersion: nv, }) - if ev.Enabled() { - vs[d.Path] = d.Version + if debug { + attrs = append(attrs, slog.String(d.Path, d.Version)) } } - ev. - Interface("versions", vs). - Msg("analyzed exe") + log.DebugContext(ctx, "analyzed exe", "versions", slog.GroupValue(attrs...)) return nil } -var versionRegex = regexp.MustCompile(`^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$`) -var ErrInvalidSemVer = errors.New("invalid semantic version") +var ( + versionRegex = regexp.MustCompile(`^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$`) + ErrInvalidSemVer = errors.New("invalid semantic version") +) // ParseVersion will return a claircore.Version of type semver given // a valid semantic version. If the string is not a valid semver it diff --git a/gobin/exe_test.go b/gobin/exe_test.go index 6ca7e7d1b..75a53956e 100644 --- a/gobin/exe_test.go +++ b/gobin/exe_test.go @@ -1,16 +1,15 @@ package gobin import ( - "context" "os" "path/filepath" "testing" "github.com/Masterminds/semver" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" + "github.com/quay/claircore/test" ) func TestBin(t *testing.T) { @@ -21,7 +20,7 @@ func TestBin(t *testing.T) { for _, n := range ms { name := filepath.Base(n) t.Run(name, func(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) f, err := os.Open(n) if err != nil { t.Fatal(err) diff --git a/gobin/gobin.go b/gobin/gobin.go index 91aad4456..763a35fe4 100644 --- a/gobin/gobin.go +++ b/gobin/gobin.go @@ -18,12 +18,11 @@ import ( "fmt" "io" "io/fs" + "log/slog" "os" "runtime/trace" "sync" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/rpm" @@ -65,12 +64,8 @@ func (Detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pack } defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", l.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "gobin/Detector.Scan", - "version", detectorVersion, - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { @@ -90,7 +85,7 @@ func (Detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pack } walk := func(p string, d fs.DirEntry, err error) error { - ctx := zlog.ContextWithValues(ctx, "filename", d.Name()) + log := slog.With("path", p) switch { case err != nil: @@ -114,9 +109,7 @@ func (Detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pack } if set.Contains(p) { - zlog.Debug(ctx). - Str("path", p). - Msg("file path determined to be of RPM origin") + log.DebugContext(ctx, "file path determined to be of RPM origin") return nil } @@ -124,7 +117,7 @@ func (Detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pack if err != nil { // TODO(crozzy): Remove log line once controller is in a // position to log all the context when receiving an error. - zlog.Warn(ctx).Msg("unable to open file") + log.WarnContext(ctx, "unable to open file") return fmt.Errorf("gobin: unable to open %q: %w", p, err) } defer f.Close() @@ -138,7 +131,7 @@ func (Detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pack default: // TODO(crozzy): Remove log line once controller is in a // position to log all the context when receiving an error. - zlog.Warn(ctx).Msg("unable to read file") + log.WarnContext(ctx, "unable to read file") return fmt.Errorf("gobin: unable to read %q: %w", p, err) } @@ -158,9 +151,7 @@ func (Detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pack case 2: // big-endian typ = binary.BigEndian.Uint16(peek[0x10:]) default: - zlog.Warn(ctx). - Uint8("endianness", e). - Msg("martian ELF") + log.WarnContext(ctx, "martian ELF", "endianness", e) } if typ != 0x02 && typ != 0x03 { // AKA [debug/elf.ET_EXEC] and [debug/elf.ET_DYN] -- not imported in this file by convention. diff --git a/gobin/gobin_test.go b/gobin/gobin_test.go index 83cf657ee..1f671ff25 100644 --- a/gobin/gobin_test.go +++ b/gobin/gobin_test.go @@ -2,7 +2,6 @@ package gobin import ( "archive/tar" - "context" "io" "os" "os/exec" @@ -10,14 +9,12 @@ import ( "strings" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/test" ) func TestEmptyFile(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) mod := test.Modtime(t, "gobin_test.go") // Needs to be the name of this file. p := test.GenerateFixture(t, "nothing.tar", mod, func(t testing.TB, tf *os.File) { @@ -74,7 +71,7 @@ func TestEmptyFile(t *testing.T) { } func TestScanner(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) mod := test.Modtime(t, "gobin_test.go") // Needs to be the name of this file. p := test.GenerateFixture(t, t.Name()+".tar", mod, func(t testing.TB, tf *os.File) { diff --git a/indexer/controller/checkmanifest.go b/indexer/controller/checkmanifest.go index 839cd0e4a..2cd510e7b 100644 --- a/indexer/controller/checkmanifest.go +++ b/indexer/controller/checkmanifest.go @@ -3,11 +3,11 @@ package controller import ( "context" "fmt" + "log/slog" "strconv" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/quay/zlog" "github.com/quay/claircore/indexer" ) @@ -35,7 +35,7 @@ func checkManifest(ctx context.Context, s *Controller) (State, error) { // if we haven't seen this manifest, determine which scanners to use, persist it // and transition to FetchLayer state. if !ok { - zlog.Info(ctx).Msg("manifest to be scanned") + slog.InfoContext(ctx, "manifest to be scanned") // if a manifest was analyzed by a particular scanner we can // omit it from this index, as all its comprising layers were analyzed @@ -61,7 +61,7 @@ func checkManifest(ctx context.Context, s *Controller) (State, error) { // we have seen this manifest before and it's been been processed with the desired scanners // retrieve the existing one and transition to Terminal. - zlog.Info(ctx).Msg("manifest already scanned") + slog.InfoContext(ctx, "manifest already scanned") sr, ok, err := s.Store.IndexReport(ctx, s.manifest.Hash) if err != nil { return Terminal, fmt.Errorf("failed to retrieve manifest: %w", err) diff --git a/indexer/controller/checkmanifest_test.go b/indexer/controller/checkmanifest_test.go index e67547bfe..911755e10 100644 --- a/indexer/controller/checkmanifest_test.go +++ b/indexer/controller/checkmanifest_test.go @@ -1,20 +1,18 @@ package controller import ( - "context" "testing" - "github.com/quay/zlog" "go.uber.org/mock/gomock" "github.com/quay/claircore" + "github.com/quay/claircore/test" indexer "github.com/quay/claircore/test/mock/indexer" ) // confirm checkManfest statefunc acts appropriately // when manifest has been seen func TestCheckManifest(t *testing.T) { - ctx := zlog.Test(context.Background(), t) tt := []struct { // the name of this test name string @@ -49,7 +47,7 @@ func TestCheckManifest(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) // get mock m := table.mock(t) diff --git a/indexer/controller/coalesce_test.go b/indexer/controller/coalesce_test.go index 6828848f8..a71eae3cb 100644 --- a/indexer/controller/coalesce_test.go +++ b/indexer/controller/coalesce_test.go @@ -1,12 +1,10 @@ package controller import ( - "context" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore/indexer" + "github.com/quay/claircore/test" ) // TestCoalesce confirms when no error is encountered @@ -16,8 +14,7 @@ import ( // This test simply provides no Ecosystems to the index // controller and does no work. func TestCoalesce(t *testing.T) { - ctx := context.Background() - var tt = []struct { + tt := []struct { name string expectedState State }{ @@ -29,7 +26,7 @@ func TestCoalesce(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) indexer := New(&indexer.Options{}) state, err := coalesce(ctx, indexer) diff --git a/indexer/controller/controller.go b/indexer/controller/controller.go index df6504201..e8b4aa814 100644 --- a/indexer/controller/controller.go +++ b/indexer/controller/controller.go @@ -4,10 +4,11 @@ import ( "context" "errors" "fmt" + "log/slog" "math/rand" "time" - "github.com/quay/zlog" + "github.com/quay/claircore/toolkit/log" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -64,12 +65,10 @@ func (s *Controller) Index(ctx context.Context, manifest *claircore.Manifest) (* // set manifest info on controller s.manifest = manifest s.report.Hash = manifest.Hash - ctx = zlog.ContextWithValues(ctx, - "component", "indexer/controller/Controller.Index", - "manifest", s.manifest.Hash.String()) + ctx = log.With(ctx, "manifest", s.manifest.Hash) s.Realizer = s.FetchArena.Realizer(ctx) defer s.Realizer.Close() - zlog.Info(ctx).Msg("starting scan") + slog.InfoContext(ctx, "starting scan") return s.report, s.run(ctx) } @@ -83,7 +82,7 @@ func (s *Controller) run(ctx context.Context) (err error) { // As long as there's not an error and the current state isn't Terminal, run // the corresponding function. for err == nil && s.currentState != Terminal { - ctx := zlog.ContextWithValues(ctx, "state", s.currentState.String()) + ctx := log.With(ctx, "state", s.currentState) next, err = stateToStateFunc[s.currentState](ctx, s) switch { case errors.Is(err, nil) && !errors.Is(ctx.Err(), nil): @@ -107,16 +106,12 @@ func (s *Controller) run(ctx context.Context) (err error) { continue default: s.setState(IndexError) - zlog.Error(ctx). - Err(err). - Msg("error during scan") + slog.ErrorContext(ctx, "error during scan", "reason", err) s.report.Success = false s.report.Err = err.Error() } if setReportErr := s.Store.SetIndexReport(ctx, s.report); !errors.Is(setReportErr, nil) { - zlog.Info(ctx). - Err(setReportErr). - Msg("failed persisting index report") + slog.InfoContext(ctx, "failed persisting index report", "reason", setReportErr) s.setState(IndexError) s.report.Err = fmt.Sprintf("failed persisting index report: %s", setReportErr.Error()) err = setReportErr diff --git a/indexer/controller/controller_test.go b/indexer/controller/controller_test.go index 99499a275..60eb340dc 100644 --- a/indexer/controller/controller_test.go +++ b/indexer/controller/controller_test.go @@ -1,16 +1,15 @@ package controller import ( - "context" "errors" "fmt" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "go.uber.org/mock/gomock" "github.com/quay/claircore" + "github.com/quay/claircore/test" indexer "github.com/quay/claircore/test/mock/indexer" ) @@ -21,7 +20,6 @@ import ( // call to s.Store.ManifestScanned forcing checkManifest to return an error and // evaluate our scanner's state afterwards. func TestControllerIndexerError(t *testing.T) { - ctx := context.Background() tt := []struct { mock func(t *testing.T) (indexer.Store, indexer.FetchArena) name string @@ -69,7 +67,7 @@ func TestControllerIndexerError(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) store, fa := table.mock(t) c := New(&indexer.Options{ Store: store, @@ -96,7 +94,6 @@ func TestControllerIndexerError(t *testing.T) { // TestControllerIndexFinished tests that our state machine does the correct // thing when it reaches ScanFinished terminal state. func TestControllerIndexFinished(t *testing.T) { - ctx := context.Background() tt := []struct { mock func(t *testing.T) (indexer.Store, indexer.FetchArena) name string @@ -126,7 +123,7 @@ func TestControllerIndexFinished(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) store, fa := table.mock(t) c := New(&indexer.Options{ Store: store, diff --git a/indexer/controller/fetchlayers.go b/indexer/controller/fetchlayers.go index 24688711f..742d4c455 100644 --- a/indexer/controller/fetchlayers.go +++ b/indexer/controller/fetchlayers.go @@ -3,26 +3,21 @@ package controller import ( "context" "fmt" - - "github.com/quay/zlog" + "log/slog" "github.com/quay/claircore/internal/wart" ) func fetchLayers(ctx context.Context, s *Controller) (State, error) { - zlog.Info(ctx).Msg("layers fetch start") - defer zlog.Info(ctx).Msg("layers fetch done") + slog.InfoContext(ctx, "layers fetch start") + defer slog.InfoContext(ctx, "layers fetch done") toFetch, err := reduce(ctx, s.Store, s.Vscnrs, s.manifest.Layers) if err != nil { return Terminal, fmt.Errorf("failed to determine layers to fetch: %w", err) } - zlog.Debug(ctx). - Int("count", len(toFetch)). - Msg("fetching layers") + slog.DebugContext(ctx, "fetching layers", "count", len(toFetch)) if err := s.Realizer.Realize(ctx, toFetch); err != nil { - zlog.Warn(ctx). - Err(err). - Msg("layers fetch failure") + slog.WarnContext(ctx, "layers fetch failure", "reason", err) return Terminal, fmt.Errorf("failed to fetch layers: %w", err) } // With the addition of the LayerDescription abstraction, it's possible that @@ -30,6 +25,6 @@ func fetchLayers(ctx context.Context, s *Controller) (State, error) { // LayerDescription type is plumbed through the Indexer, this can be // removed. wart.CopyLayerPointers(s.manifest.Layers, toFetch) - zlog.Info(ctx).Msg("layers fetch success") + slog.InfoContext(ctx, "layers fetch success") return ScanLayers, nil } diff --git a/indexer/controller/indexfinished.go b/indexer/controller/indexfinished.go index bd5e47fc2..d96525f16 100644 --- a/indexer/controller/indexfinished.go +++ b/indexer/controller/indexfinished.go @@ -3,8 +3,7 @@ package controller import ( "context" "fmt" - - "github.com/quay/zlog" + "log/slog" ) // indexFinished is the terminal stateFunc. once it transitions the @@ -12,13 +11,13 @@ import ( // and return an IndexReport to the caller func indexFinished(ctx context.Context, s *Controller) (State, error) { s.report.Success = true - zlog.Info(ctx).Msg("finishing scan") + slog.InfoContext(ctx, "finishing scan") err := s.Store.SetIndexFinished(ctx, s.report, s.Vscnrs) if err != nil { return Terminal, fmt.Errorf("failed finish scan: %w", err) } - zlog.Info(ctx).Msg("manifest successfully scanned") + slog.InfoContext(ctx, "manifest successfully scanned") return Terminal, nil } diff --git a/indexer/controller/indexfinished_test.go b/indexer/controller/indexfinished_test.go index 83da52819..49c4c8b5f 100644 --- a/indexer/controller/indexfinished_test.go +++ b/indexer/controller/indexfinished_test.go @@ -1,17 +1,15 @@ package controller import ( - "context" "testing" - "github.com/quay/zlog" "go.uber.org/mock/gomock" + "github.com/quay/claircore/test" indexer "github.com/quay/claircore/test/mock/indexer" ) func TestIndexFinished(t *testing.T) { - ctx := context.Background() tt := []struct { name string expectedState State @@ -33,7 +31,7 @@ func TestIndexFinished(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) store := table.mock(t) scnr := New(&indexer.Options{ Store: store, diff --git a/indexer/controller/indexmanifest.go b/indexer/controller/indexmanifest.go index 272807c2a..25f919703 100644 --- a/indexer/controller/indexmanifest.go +++ b/indexer/controller/indexmanifest.go @@ -3,12 +3,11 @@ package controller import ( "context" "fmt" - - "github.com/quay/zlog" + "log/slog" ) func indexManifest(ctx context.Context, c *Controller) (State, error) { - zlog.Info(ctx).Msg("starting index manifest") + slog.InfoContext(ctx, "starting index manifest") if c.report == nil { return Terminal, fmt.Errorf("reached IndexManifest state with a nil report field. cannot continue") diff --git a/indexer/controller/indexmanifest_test.go b/indexer/controller/indexmanifest_test.go index 1bd40b577..25e911bca 100644 --- a/indexer/controller/indexmanifest_test.go +++ b/indexer/controller/indexmanifest_test.go @@ -1,18 +1,16 @@ package controller import ( - "context" "fmt" "testing" - "github.com/quay/zlog" "go.uber.org/mock/gomock" + "github.com/quay/claircore/test" indexer "github.com/quay/claircore/test/mock/indexer" ) func TestIndexManifest(t *testing.T) { - ctx := context.Background() tt := []struct { name string expectedState State @@ -44,7 +42,7 @@ func TestIndexManifest(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) s := table.mock(t) indexer := New(&indexer.Options{ Store: s, diff --git a/indexer/controller/reduce.go b/indexer/controller/reduce.go index d8cbb8d30..6890b44ca 100644 --- a/indexer/controller/reduce.go +++ b/indexer/controller/reduce.go @@ -2,8 +2,7 @@ package controller import ( "context" - - "github.com/quay/zlog" + "log/slog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -16,10 +15,7 @@ func reduce(ctx context.Context, store indexer.Store, scnrs indexer.VersionedSca for _, scnr := range scnrs { ok, err := store.LayerScanned(ctx, l.Hash, scnr) if err != nil { - zlog.Debug(ctx). - Stringer("layer", l.Hash). - Err(err). - Msg("unable to lookup layer") + slog.DebugContext(ctx, "unable to lookup layer", "layer", l.Hash, "reason", err) return nil, err } if !ok { diff --git a/indexer/controller/scanlayers.go b/indexer/controller/scanlayers.go index aeda09061..21c612635 100644 --- a/indexer/controller/scanlayers.go +++ b/indexer/controller/scanlayers.go @@ -3,19 +3,18 @@ package controller import ( "context" "fmt" - - "github.com/quay/zlog" + "log/slog" ) // scanLayers will run all scanner types against all layers if deemed necessary // to scan func scanLayers(ctx context.Context, c *Controller) (State, error) { - zlog.Info(ctx).Msg("layers scan start") - defer zlog.Info(ctx).Msg("layers scan done") + slog.InfoContext(ctx, "layers scan start") + defer slog.InfoContext(ctx, "layers scan done") err := c.LayerScanner.Scan(ctx, c.manifest.Hash, c.manifest.Layers) if err != nil { return Terminal, fmt.Errorf("failed to scan all layer contents: %w", err) } - zlog.Debug(ctx).Msg("layers scan ok") + slog.DebugContext(ctx, "layers scan ok") return Coalesce, nil } diff --git a/indexer/controller/scanlayers_test.go b/indexer/controller/scanlayers_test.go index a359b5365..b710bb0de 100644 --- a/indexer/controller/scanlayers_test.go +++ b/indexer/controller/scanlayers_test.go @@ -6,7 +6,6 @@ import ( "fmt" "testing" - "github.com/quay/zlog" "go.uber.org/mock/gomock" "github.com/quay/claircore" @@ -17,7 +16,6 @@ import ( ) func TestScanLayers(t *testing.T) { - ctx := context.Background() tt := []struct { mock func(t *testing.T) indexer.Store name string @@ -38,7 +36,7 @@ func TestScanLayers(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) s := table.mock(t) opts := &indexer.Options{ Store: s, @@ -62,7 +60,7 @@ func TestScanLayers(t *testing.T) { } func TestScanNoErrors(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) ctrl := gomock.NewController(t) store := indexer_mock.NewMockStore(ctrl) diff --git a/indexer/ecosystem.go b/indexer/ecosystem.go index 5f2ebc0e3..5e49267a0 100644 --- a/indexer/ecosystem.go +++ b/indexer/ecosystem.go @@ -2,11 +2,9 @@ package indexer import ( "context" - - "github.com/quay/zlog" ) -// Ecosystems group together scanners and a Coalescer which are commonly used +// An Ecosystem groups together scanners and a Coalescer which are commonly used // together. // // A typical ecosystem is "dpkg" which will use the "dpkg" package indexer, the @@ -26,7 +24,6 @@ type Ecosystem struct { // EcosystemsToScanners extracts and dedupes multiple ecosystems and returns // their discrete scanners. func EcosystemsToScanners(ctx context.Context, ecosystems []*Ecosystem) ([]PackageScanner, []DistributionScanner, []RepositoryScanner, []FileScanner, error) { - ctx = zlog.ContextWithValues(ctx, "component", "indexer/EcosystemsToScanners") ps := []PackageScanner{} ds := []DistributionScanner{} rs := []RepositoryScanner{} diff --git a/indexer/layerscanner.go b/indexer/layerscanner.go index 1f91b7e19..d93de7865 100644 --- a/indexer/layerscanner.go +++ b/indexer/layerscanner.go @@ -4,10 +4,11 @@ import ( "context" "errors" "fmt" + "log/slog" "net" "runtime" - "github.com/quay/zlog" + "github.com/quay/claircore/toolkit/log" "golang.org/x/sync/errgroup" "github.com/quay/claircore" @@ -30,13 +31,10 @@ type LayerScanner struct { // // The provided Context is only used for the duration of the call. func NewLayerScanner(ctx context.Context, concurrent int, opts *Options) (*LayerScanner, error) { - ctx = zlog.ContextWithValues(ctx, "component", "indexer.NewLayerScanner") - zlog.Info(ctx).Msg("NewLayerScanner: constructing a new layer-scanner") + slog.InfoContext(ctx, "constructing") switch { case concurrent < 1: - zlog.Warn(ctx). - Int("value", concurrent). - Msg("rectifying nonsense 'concurrent' argument") + slog.WarnContext(ctx, "rectifying nonsense 'concurrent' argument", "value", concurrent) fallthrough case concurrent == 0: concurrent = runtime.GOMAXPROCS(0) @@ -61,6 +59,7 @@ func configAndFilter[S VersionedScanner](ctx context.Context, opts *Options, ss i := 0 for _, s := range ss { n := s.Name() + log := slog.With("scanner", n) var cfgMap map[string]func(any) error switch k := s.Kind(); k { case "package": @@ -72,10 +71,7 @@ func configAndFilter[S VersionedScanner](ctx context.Context, opts *Options, ss case "file": cfgMap = opts.ScannerConfig.File default: - zlog.Warn(ctx). - Str("kind", k). - Str("scanner", n). - Msg("unknown scanner kind") + log.WarnContext(ctx, "unknown scanner kind", "kind", k) continue } @@ -87,25 +83,17 @@ func configAndFilter[S VersionedScanner](ctx context.Context, opts *Options, ss rs, rsOK := any(s).(RPCScanner) switch { case haveCfg && !csOK && !rsOK: - zlog.Warn(ctx). - Str("scanner", n). - Msg("configuration present for an unconfigurable scanner, skipping") + log.WarnContext(ctx, "configuration present for an unconfigurable scanner, skipping") case csOK && rsOK: fallthrough case !csOK && rsOK: if err := rs.Configure(ctx, f, opts.Client); err != nil { - zlog.Error(ctx). - Str("scanner", n). - Err(err). - Msg("configuration failed") + log.ErrorContext(ctx, "configuration failed", "reason", err) continue } case csOK && !rsOK: if err := cs.Configure(ctx, f); err != nil { - zlog.Error(ctx). - Str("scanner", n). - Err(err). - Msg("configuration failed") + log.ErrorContext(ctx, "configuration failed", "reason", err) continue } } @@ -125,9 +113,7 @@ func configAndFilter[S VersionedScanner](ctx context.Context, opts *Options, ss // The provided Context controls cancellation for all scanners. The first error // reported halts all work and is returned from Scan. func (ls *LayerScanner) Scan(ctx context.Context, manifest claircore.Digest, layers []*claircore.Layer) error { - ctx = zlog.ContextWithValues(ctx, - "component", "indexer/LayerScanner.Scan", - "manifest", manifest.String()) + ctx = log.With(ctx, "manifest", manifest) g, ctx := errgroup.WithContext(ctx) // Using the goroutine's built-in limit is worst-case the same as using an @@ -183,20 +169,16 @@ Layers: // ScanLayer (along with the result type) handles an individual (scanner, layer) // pair. func (ls *LayerScanner) scanLayer(ctx context.Context, l *claircore.Layer, s VersionedScanner) error { - ctx = zlog.ContextWithValues(ctx, - "component", "indexer/LayerScanner.scanLayer", - "scanner", s.Name(), - "kind", s.Kind(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("scan start") - defer zlog.Debug(ctx).Msg("scan done") + ctx = log.With(ctx, "scanner", s.Name(), "kind", s.Kind(), "layer", l.Hash) + slog.DebugContext(ctx, "scan start") + defer slog.DebugContext(ctx, "scan done") ok, err := ls.store.LayerScanned(ctx, l.Hash, s) if err != nil { return err } if ok { - zlog.Debug(ctx).Msg("layer already scanned") + slog.DebugContext(ctx, "layer already scanned") return nil } @@ -251,10 +233,10 @@ func (r *result) Do(ctx context.Context, s VersionedScanner, l *claircore.Layer) switch { case errors.Is(err, nil): case errors.As(err, &addrErr): - zlog.Warn(ctx).Str("scanner", s.Name()).Err(err).Msg("scanner not able to access resources") + slog.WarnContext(ctx, "scanner not able to access resources", "scanner", s.Name(), "reason", err) return nil default: - zlog.Info(ctx).Err(err).Send() + slog.InfoContext(ctx, "unexpected error", "reason", err) } return err @@ -264,25 +246,25 @@ func (r *result) Do(ctx context.Context, s VersionedScanner, l *claircore.Layer) // the result. func (r *result) Store(ctx context.Context, store Store, s VersionedScanner, l *claircore.Layer) error { if r.pkgs != nil { - zlog.Debug(ctx).Int("count", len(r.pkgs)).Msg("scan returned packages") + slog.DebugContext(ctx, "scan returned packages", "count", len(r.pkgs)) if err := store.IndexPackages(ctx, r.pkgs, l, s); err != nil { return err } } if r.dists != nil { - zlog.Debug(ctx).Int("count", len(r.dists)).Msg("scan returned dists") + slog.DebugContext(ctx, "scan returned distributions", "count", len(r.dists)) if err := store.IndexDistributions(ctx, r.dists, l, s); err != nil { return err } } if r.repos != nil { - zlog.Debug(ctx).Int("count", len(r.repos)).Msg("scan returned repos") + slog.DebugContext(ctx, "scan returned repositories", "count", len(r.repos)) if err := store.IndexRepositories(ctx, r.repos, l, s); err != nil { return err } } if r.files != nil { - zlog.Debug(ctx).Int("count", len(r.files)).Msg("scan returned files") + slog.DebugContext(ctx, "scan returned files", "count", len(r.files)) if err := store.IndexFiles(ctx, r.files, l, s); err != nil { return err } diff --git a/internal/dnf/dnf.go b/internal/dnf/dnf.go index 7c6ac4962..f6c36370e 100644 --- a/internal/dnf/dnf.go +++ b/internal/dnf/dnf.go @@ -13,12 +13,12 @@ import ( "io" "io/fs" "iter" + "log/slog" "net/url" "os" "runtime" "slices" - "github.com/quay/zlog" _ "modernc.org/sqlite" // register the sqlite driver "github.com/quay/claircore" @@ -85,7 +85,7 @@ func FindRepoids(ctx context.Context, sys fs.FS) ([]string, error) { } defer func() { if err := rows.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("error closing returned rows") + slog.WarnContext(ctx, "error closing returned rows", "reason", err) } }() @@ -145,7 +145,7 @@ Stat: } defer func() { if err := f.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close fs.FS db file") + slog.WarnContext(ctx, "unable to close fs.FS db file", "reason", err) } }() @@ -157,17 +157,17 @@ Stat: } defer func() { if err := spool.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close sqlite db file") + slog.WarnContext(ctx, "unable to close sqlite db file", "reason", err) } // If in an error return, make sure to clean up the spool file. if h == nil { if err := os.Remove(spool.Name()); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to unlink sqlite db file") + slog.WarnContext(ctx, "unable to unlink sqlite db file", "reason", err) } } }() - zlog.Debug(ctx).Str("file", spool.Name()).Msg("copying sqlite db out of tar") + slog.DebugContext(ctx, "copying sqlite db out of tar", "file", spool.Name()) if _, err := io.Copy(spool, f); err != nil { return nil, fmt.Errorf("internal/dnf: error spooling sqlite db: %w", err) } @@ -181,7 +181,7 @@ Stat: } if err := db.PingContext(ctx); err != nil { if err := db.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close sqlite db") + slog.WarnContext(ctx, "unable to close sqlite db", "reason", err) } return nil, fmt.Errorf("internal/dnf: error pinging sqlite db: %w", err) } @@ -210,7 +210,7 @@ func pickQueries(ctx context.Context, db *sql.DB) (q queries, err error) { if err != nil { return q, err } - zlog.Debug(ctx).Strs("tables", names).Msg("found tables in database") + slog.DebugContext(ctx, "found tables in database", "tables", names) switch { case !slices.Contains(names, `config`): @@ -260,17 +260,16 @@ func (h *historyDB) AddRepoid(ctx context.Context, pkg *claircore.Package) error v := fmt.Sprintf("%s-%s.%s", pkg.Name, pkg.Version, pkg.Arch) // "Version" contains the EVR. ver, err := rpmver.Parse(v) if err != nil { - zlog.Warn(ctx). - Err(err). - Str("version", v). - Msg("unable to re-parse rpm version") + slog.WarnContext(ctx, "unable to re-parse rpm version", + "version", v, + "reason", err, + ) return nil } if ver.Architecture == nil { - zlog.Debug(ctx). - Err(err). - Str("version", v). - Msg("unable to parse architecture") + slog.DebugContext(ctx, "unable to parse architecture", + "reason", err, + "version", v) return nil } diff --git a/internal/dnf/dnf_test.go b/internal/dnf/dnf_test.go index 6e8a550a4..adc9d80d3 100644 --- a/internal/dnf/dnf_test.go +++ b/internal/dnf/dnf_test.go @@ -10,9 +10,9 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" + "github.com/quay/claircore/test" ) type testCase struct { @@ -24,7 +24,7 @@ type testCase struct { func (tc *testCase) Run(ctx context.Context, t *testing.T) { t.Run(tc.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) seq := func(yield func(claircore.Package, error) bool) { yield(tc.Package, nil) } @@ -43,7 +43,7 @@ func (tc *testCase) Run(ctx context.Context, t *testing.T) { func TestWrap(t *testing.T) { t.Run("dnf4", func(t *testing.T) { - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) sys := os.DirFS(filepath.Join("testdata", path.Base(t.Name()))) tcs := []testCase{ @@ -77,7 +77,7 @@ func TestWrap(t *testing.T) { } }) t.Run("dnf5", func(t *testing.T) { - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) sys := os.DirFS(filepath.Join("testdata", path.Base(t.Name()))) tcs := []testCase{ @@ -129,7 +129,7 @@ func TestFindRepoids(t *testing.T) { for _, tc := range tcs { t.Run(tc.Name, func(t *testing.T) { - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) sys := os.DirFS(filepath.Join("testdata", tc.Name)) got, err := FindRepoids(ctx, sys) diff --git a/internal/matcher/controller.go b/internal/matcher/controller.go index c67774506..a5e17e363 100644 --- a/internal/matcher/controller.go +++ b/internal/matcher/controller.go @@ -2,10 +2,9 @@ package matcher import ( "context" + "log/slog" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/datastore" "github.com/quay/claircore/libvuln/driver" @@ -30,15 +29,12 @@ func NewController(m driver.Matcher, store datastore.Vulnerability) *Controller // Match is the entrypoint for [Controller]. func (mc *Controller) Match(ctx context.Context, records []*claircore.IndexRecord) (map[string][]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "internal/matcher/Controller.Match", - "matcher", mc.m.Name()) + log := slog.With("matcher", mc.m.Name()) // find the packages the matcher is interested in. interested := mc.findInterested(records) - zlog.Debug(ctx). - Int("interested", len(interested)). - Int("records", len(records)). - Msg("interest") + log.DebugContext(ctx, "interest", + "interested", len(interested), + "records", len(records)) // early return; do not call db at all if len(interested) == 0 { @@ -48,26 +44,23 @@ func (mc *Controller) Match(ctx context.Context, records []*claircore.IndexRecor remoteMatcher, matchedVulns, err := mc.queryRemoteMatcher(ctx, interested) if remoteMatcher { if err != nil { - zlog.Error(ctx).Err(err).Msg("remote matcher error, returning empty results") + log.ErrorContext(ctx, "remote matcher error, returning empty results", "reason", err) return map[string][]*claircore.Vulnerability{}, nil } return matchedVulns, nil } dbSide, authoritative := mc.dbFilter() - zlog.Debug(ctx). - Bool("opt-in", dbSide). - Bool("authoritative", authoritative). - Msg("version filter compatible?") + log.DebugContext(ctx, "version filter compatible?", + "opt-in", dbSide, + "authoritative", authoritative) // query the vulnstore vulns, err := mc.query(ctx, interested, dbSide) if err != nil { return nil, err } - zlog.Debug(ctx). - Int("vulnerabilities", len(vulns)). - Msg("query") + log.DebugContext(ctx, "query", "count", len(vulns)) if authoritative { return vulns, nil @@ -77,9 +70,7 @@ func (mc *Controller) Match(ctx context.Context, records []*claircore.IndexRecor if err != nil { return nil, err } - zlog.Debug(ctx). - Int("filtered", len(filteredVulns)). - Msg("filtered") + log.DebugContext(ctx, "filtered", "count", len(filteredVulns)) return filteredVulns, nil } diff --git a/internal/matcher/match.go b/internal/matcher/match.go index aa67f814a..3ba8eb372 100644 --- a/internal/matcher/match.go +++ b/internal/matcher/match.go @@ -5,11 +5,11 @@ import ( "encoding/json" "errors" "fmt" + "log/slog" "runtime" "sync" "sync/atomic" - "github.com/quay/zlog" "golang.org/x/sync/errgroup" "github.com/quay/claircore" @@ -202,15 +202,11 @@ func EnrichedMatch(ctx context.Context, ir *claircore.IndexReport, ms []driver.M for e = range eCh { kind, msg, err := e.Enrich(ectx, getter(s, e.Name()), vr) if err != nil { - zlog.Error(ctx). - Err(err). - Msg("enrichment error") + slog.ErrorContext(ctx, "enrichment error", "reason", err) continue } if len(msg) == 0 { - zlog.Debug(ctx). - Str("name", e.Name()). - Msg("enricher reported nothing, skipping") + slog.DebugContext(ctx, "enricher reported nothing, skipping", "name", e.Name()) continue } res := entry{ diff --git a/internal/rpm/bdb/bdb.go b/internal/rpm/bdb/bdb.go index caab00fb3..63242da0b 100644 --- a/internal/rpm/bdb/bdb.go +++ b/internal/rpm/bdb/bdb.go @@ -7,8 +7,7 @@ import ( "fmt" "io" "iter" - - "github.com/quay/zlog" + "log/slog" ) // PackageDB is the "pkgdb" a.k.a. "Packages", the raw package data. @@ -258,10 +257,9 @@ func (db *PackageDB) Headers(ctx context.Context) iter.Seq2[io.ReaderAt, error] } // Double-check we'll read the intended amount. if got, want := r.Size(), int64(offpg.Length); got != want { - zlog.Info(ctx). - Int64("got", got). - Int64("want", want). - Msg("bdb: expected data length botch") + slog.InfoContext(ctx, "expected data length botch", + "got", got, + "want", want) } if !yield(&r, nil) { diff --git a/internal/rpm/bdb/bdb_test.go b/internal/rpm/bdb/bdb_test.go index a45d06e50..e9713550b 100644 --- a/internal/rpm/bdb/bdb_test.go +++ b/internal/rpm/bdb/bdb_test.go @@ -2,19 +2,15 @@ package bdb import ( "bytes" - "context" "io/fs" "os" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore/internal/rpm/rpmdb" + "github.com/quay/claircore/test" ) func TestLoadPackage(t *testing.T) { - ctx := context.Background() - dir := os.DirFS("testdata") ms, err := fs.Glob(dir, "*Packages") if err != nil || len(ms) == 0 { @@ -22,7 +18,7 @@ func TestLoadPackage(t *testing.T) { } for _, n := range ms { t.Run(n, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) b, err := fs.ReadFile(dir, n) if err != nil { t.Fatal(err) diff --git a/internal/rpm/bdb/doc.go b/internal/rpm/bdb/doc.go index 093126a25..a44db4c9c 100644 --- a/internal/rpm/bdb/doc.go +++ b/internal/rpm/bdb/doc.go @@ -6,8 +6,7 @@ import ( "context" "encoding/binary" "io" - - "github.com/quay/zlog" + "log/slog" ) // CheckMagic looks at bit of the provided Reader to see if it looks like a @@ -28,7 +27,7 @@ func CheckMagic(ctx context.Context, r io.Reader) bool { b := make([]byte, 16) if _, err := io.ReadFull(r, b); err != nil { - zlog.Warn(ctx).Err(err).Msg("unexpected error checking magic") + slog.WarnContext(ctx, "unexpected error checking magic", "reason", err) return false } // Look at position 12 for a magic number. diff --git a/internal/rpm/database.go b/internal/rpm/database.go index c8e8bb4a0..49615d9f7 100644 --- a/internal/rpm/database.go +++ b/internal/rpm/database.go @@ -5,12 +5,11 @@ import ( "fmt" "io" "iter" + "log/slog" "runtime/trace" "strings" "sync" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/internal/rpm/rpmdb" "github.com/quay/claircore/internal/rpmver" @@ -45,9 +44,7 @@ func (db *Database) Packages(ctx context.Context) iter.Seq2[claircore.Package, e var ok bool ct := 0 defer func() { - zlog.Debug(ctx). - Int("packages", ct). - Msg("processed rpm db") + slog.DebugContext(ctx, "processed rpm db", "packages", ct) }() retErr := func(err error) (cont bool) { trace.WithRegion(ctx, "internal/rpm.Database.PackagesYield", func() { cont = yield(claircore.Package{}, err) }) @@ -87,14 +84,11 @@ func (db *Database) Packages(ctx context.Context) iter.Seq2[claircore.Package, e for !ok { v, err := rpmver.Parse(srcRPM) if err != nil { - zlog.Info(ctx). - Err(err). - Msg("unable to parse SOURCERPM tag, skipping") + slog.InfoContext(ctx, "unable to parse SOURCERPM tag, skipping", "reason", err) break } if v.Name == nil { - zlog.Info(ctx). - Msg("no name parse out of SOURCERPM tag, skipping") + slog.InfoContext(ctx, "no name parse out of SOURCERPM tag, skipping") break } src := claircore.Package{ @@ -135,39 +129,31 @@ var sourceVersionWarning sync.Once func printSourceVersionWarning(ctx context.Context) { sourceVersionWarning.Do(func() { - zlog.Warn(ctx). - Strs("see-also", []string{ + slog.WarnContext(ctx, "rpm source packages always record 0 epoch; this may cause incorrect matching", + "see-also", strings.Join([]string{ `https://github.com/rpm-software-management/rpm/issues/2796`, `https://github.com/rpm-software-management/rpm/discussions/3703`, `https://github.com/rpm-software-management/rpm/pull/3755`, - }). - Msg("rpm source packages always record 0 epoch; this may cause incorrect matching") + }, " ")) }) } // PopulatePathSet adds relevant paths from the RPM database to the provided // [PathSet]. -func (db *Database) populatePathSet(ctx context.Context, s *PathSet) error { +func (db *Database) populatePathSet(ctx context.Context, s *PathSet) (int, error) { ctx, task := trace.NewTask(ctx, "internal/rpm.Database.populatePathSet") defer task.End() seq := loadPackageInfo(ctx, db.headers.Headers(ctx)) ct := 0 - defer func() { - zlog.Debug(ctx). - Int("packages", ct). - Int("files", s.len()). - Msg("processed rpm db") - }() - for info, err := range seq { if err != nil { - return err + return 0, err } ct++ info.InsertIntoSet(s) } - return nil + return ct, nil } func (db *Database) Close() error { diff --git a/internal/rpm/files.go b/internal/rpm/files.go index b5998122f..6d41b8e8e 100644 --- a/internal/rpm/files.go +++ b/internal/rpm/files.go @@ -4,13 +4,13 @@ import ( "context" "errors" "fmt" + "log/slog" "runtime" "strings" "sync" "unique" "weak" - "github.com/quay/zlog" "golang.org/x/sync/singleflight" "github.com/quay/claircore" @@ -69,18 +69,22 @@ func (c *fileCache) GetPathSet(ctx context.Context, layer *claircore.Layer) (*Pa }() for found := range seq { - zlog.Debug(ctx). - Stringer("db", found). - Msg("found possible database") + slog.DebugContext(ctx, "found possible database", "db", found) err = func() error { db, err := OpenDB(ctx, sys, found) if err != nil { return err } defer db.Close() - ctx := zlog.ContextWithValues(ctx, "db", db.String()) - zlog.Debug(ctx).Msg("examining database") - return db.populatePathSet(ctx, set) + log := slog.With("db", db) + log.DebugContext(ctx, "examining database") + ct, err := db.populatePathSet(ctx, set) + if err == nil { + log.DebugContext(ctx, "processed rpm db", + "packages", ct, + "files", set.len()) + } + return err }() if err != nil { return nil, err diff --git a/internal/rpm/files_test.go b/internal/rpm/files_test.go index a0939314c..25b3052e8 100644 --- a/internal/rpm/files_test.go +++ b/internal/rpm/files_test.go @@ -7,8 +7,6 @@ import ( "unique" "weak" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/test" ) @@ -27,7 +25,7 @@ type FileCheckerTestcase struct { func (tc *FileCheckerTestcase) Run(ctx context.Context, t *testing.T, a *test.CachedArena) { t.Run(tc.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) a.LoadLayerFromRegistry(ctx, t, tc.Layer) r := a.Realizer(ctx).(*test.CachedRealizer) t.Cleanup(func() { @@ -56,7 +54,7 @@ func (tc *FileCheckerTestcase) Run(ctx context.Context, t *testing.T, a *test.Ca for _, tc := range tc.Testcases { t.Run(tc.Name, func(t *testing.T) { t.Parallel() - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -74,7 +72,7 @@ func (tc *FileCheckerTestcase) Run(ctx context.Context, t *testing.T, a *test.Ca } func TestIsRPMFile(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) a := test.NewCachedArena(t) t.Cleanup(func() { diff --git a/internal/rpm/find.go b/internal/rpm/find.go index 96be11e96..b31d4cbc4 100644 --- a/internal/rpm/find.go +++ b/internal/rpm/find.go @@ -7,10 +7,10 @@ import ( "io" "io/fs" "iter" + "log/slog" "os" "path" - "github.com/quay/zlog" "golang.org/x/sync/errgroup" "github.com/quay/claircore/internal/rpm/bdb" @@ -166,7 +166,7 @@ func OpenDB(ctx context.Context, sys fs.FS, found FoundDB) (*Database, error) { } defer func() { if err := f.Close(); err != nil { - zlog.Warn(ctx).Stringer("kind", found.kind).Err(err).Msg("unable to close db") + slog.WarnContext(ctx, "unable to close db", "kind", found, "reason", err) } }() @@ -180,10 +180,9 @@ func OpenDB(ctx context.Context, sys fs.FS, found FoundDB) (*Database, error) { if err != nil { return nil, fmt.Errorf("internal/rpm: error spooling db: %w", err) } - ctx = zlog.ContextWithValues(ctx, "file", spool.Name()) + log := slog.With("file", spool.Name()) cleanup.spool = spool - zlog.Debug(ctx). - Msg("copying db out of fs.FS") + log.DebugContext(ctx, "copying db out of fs.FS") // Need to have the file linked into the filesystem for the sqlite package. // @@ -206,12 +205,12 @@ func OpenDB(ctx context.Context, sys fs.FS, found FoundDB) (*Database, error) { // [this post]: https://sqlite.org/forum/info/57aaaf20cf703d301fed5aeaef59e70723f1d9454fb3a4e6383b2bfac6897e5a if _, err := io.Copy(spool, f); err != nil { if err := spool.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + log.WarnContext(ctx, "unable to close spool", "reason", err) } return nil, fmt.Errorf("internal/rpm: error spooling db: %w", err) } if err := spool.Sync(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to sync spool; results may be Weird") + log.WarnContext(ctx, "unable to sync spool; results may be Weird", "reason", err) } switch found.kind { @@ -219,10 +218,10 @@ func OpenDB(ctx context.Context, sys fs.FS, found FoundDB) (*Database, error) { sdb, err := sqlite.Open(spool.Name()) if err != nil { if err := spool.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + log.WarnContext(ctx, "unable to close spool", "reason", err) } if err := os.Remove(spool.Name()); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to remove spool") + log.WarnContext(ctx, "unable to remove spool", "reason", err) } return nil, fmt.Errorf("internal/rpm: unable to open sqlite db: %w", err) } @@ -243,9 +242,7 @@ func OpenDB(ctx context.Context, sys fs.FS, found FoundDB) (*Database, error) { default: panic("unreachable") } - zlog.Debug(ctx). - Stringer("db", found). - Msg("opened database") + log.DebugContext(ctx, "opened database", "db", found) if v, ok := db.headers.(validator); ok { if err := v.Validate(ctx); err != nil { diff --git a/internal/rpm/ndb/package_test.go b/internal/rpm/ndb/package_test.go index 3014725bd..455c94c1c 100644 --- a/internal/rpm/ndb/package_test.go +++ b/internal/rpm/ndb/package_test.go @@ -2,19 +2,14 @@ package ndb import ( "bytes" - "context" "io/fs" "os" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore/internal/rpm/rpmdb" ) func TestLoadPackage(t *testing.T) { - ctx := context.Background() - dir := os.DirFS("testdata") ms, err := fs.Glob(dir, "Packages*.db") if err != nil || len(ms) == 0 { @@ -22,7 +17,7 @@ func TestLoadPackage(t *testing.T) { } for _, n := range ms { t.Run(n, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := t.Context() b, err := fs.ReadFile(dir, n) if err != nil { t.Fatal(err) diff --git a/internal/rpm/rpmdb/header_test.go b/internal/rpm/rpmdb/header_test.go index 6f1331dd5..e4b5f5806 100644 --- a/internal/rpm/rpmdb/header_test.go +++ b/internal/rpm/rpmdb/header_test.go @@ -1,15 +1,12 @@ package rpmdb import ( - "context" "os" "testing" - - "github.com/quay/zlog" ) func TestParseHeader(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := t.Context() f, err := os.Open(`testdata/package.header`) if err != nil { t.Fatal(err) diff --git a/internal/rpm/sqlite/sqlite_test.go b/internal/rpm/sqlite/sqlite_test.go index e22ed6c75..92a994d9f 100644 --- a/internal/rpm/sqlite/sqlite_test.go +++ b/internal/rpm/sqlite/sqlite_test.go @@ -1,7 +1,6 @@ package sqlite import ( - "context" "encoding/json" "hash/crc64" "io" @@ -10,11 +9,10 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" ) func TestPackages(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := t.Context() h := crc64.New(crc64.MakeTable(crc64.ISO)) // Copying to a tempdir is needed if the tests are being run from a prepared @@ -87,7 +85,7 @@ func TestPackages(t *testing.T) { } func TestValidate(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := t.Context() dbfile := filepath.Join(t.TempDir(), `no_packages.sqlite`) dst, err := os.Create(dbfile) diff --git a/java/jar/jar.go b/java/jar/jar.go index cadc50596..0eba71234 100644 --- a/java/jar/jar.go +++ b/java/jar/jar.go @@ -36,13 +36,14 @@ import ( "fmt" "io" "io/fs" + "log/slog" "net/textproto" "path" "path/filepath" "regexp" "strings" - "github.com/quay/zlog" + "github.com/quay/claircore/toolkit/log" ) // MinSize is the absolute minimum size for a jar. @@ -60,10 +61,7 @@ const MinSize = 22 // The provided name is expected to be the full path within the layer to the jar // file being provided as "z". func Parse(ctx context.Context, name string, z *zip.Reader) ([]Info, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "java/jar/Parse", - "jar", name) - return parse(ctx, srcPath{name}, z) + return parse(log.With(ctx, "jar", name), srcPath{name}, z) } // SrcPath is a helper for tracking where an archive member is. @@ -90,9 +88,7 @@ func (p *srcPath) Pop() string { // Parse is the inner function that uses a srcPath to keep track of recursions. func parse(ctx context.Context, name srcPath, z *zip.Reader) ([]Info, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "java/jar/Parse", - "name", name.String()) + ctx = log.With(ctx, "name", name.String()) // This uses an admittedly non-idiomatic, C-like goto construction. We want // to attempt a few heuristics and keep the results of the first one that @@ -108,8 +104,7 @@ func parse(ctx context.Context, name srcPath, z *zip.Reader) ([]Info, error) { ret, err = extractProperties(ctx, name, z) switch { case errors.Is(err, nil): - zlog.Debug(ctx). - Msg("using discovered properties file(s)") + slog.DebugContext(ctx, "using discovered properties file(s)") goto Finish case errors.Is(err, errUnpopulated): case strings.HasPrefix(base, "javax") && errors.Is(err, ErrNotAJar): @@ -120,8 +115,7 @@ func parse(ctx context.Context, name srcPath, z *zip.Reader) ([]Info, error) { i, err = extractManifest(ctx, name, z) switch { case errors.Is(err, nil): - zlog.Debug(ctx). - Msg("using discovered manifest") + slog.DebugContext(ctx, "using discovered manifest") ret = append(ret, i) goto Finish case errors.Is(err, errUnpopulated) || errors.Is(err, errInsaneManifest): @@ -133,8 +127,7 @@ func parse(ctx context.Context, name srcPath, z *zip.Reader) ([]Info, error) { i, err = checkName(ctx, name.Cur()) switch { case errors.Is(err, nil): - zlog.Debug(ctx). - Msg("using name mangling") + slog.DebugContext(ctx, "using name mangling") ret = append(ret, i) goto Finish case errors.Is(err, errUnpopulated): @@ -154,9 +147,7 @@ Finish: return nil, archiveErr(name, err) } if ct := len(inner); ct != 0 { - zlog.Debug(ctx). - Int("count", ct). - Msg("found embedded jars") + slog.DebugContext(ctx, "found embedded jars", "count", ct) } ret = append(ret, inner...) @@ -210,14 +201,12 @@ func extractProperties(ctx context.Context, name srcPath, z *zip.Reader) ([]Info // encoded in the file names. p := normName(f.Name) if path.Base(p) == filename { - zlog.Debug(ctx). - Str("path", p). - Msg("found properties file") + slog.DebugContext(ctx, "found properties file", "path", p) pf = append(pf, p) } } if len(pf) == 0 { - zlog.Debug(ctx).Msg("properties not found") + slog.DebugContext(ctx, "properties not found") return nil, errUnpopulated } ret := make([]Info, len(pf)) @@ -244,7 +233,7 @@ func extractProperties(ctx context.Context, name srcPath, z *zip.Reader) ([]Info // ExtractInner recurses into anything that looks like a jar in "z". func extractInner(ctx context.Context, p srcPath, z *zip.Reader) ([]Info, error) { - ctx = zlog.ContextWithValues(ctx, "parent", p.String()) + ctx = log.With(ctx, "parent", p.String()) var ret []Info // Zips need random access, so allocate a buffer for any we find. var buf bytes.Buffer @@ -258,7 +247,7 @@ func extractInner(ctx context.Context, p srcPath, z *zip.Reader) ([]Info, error) fi := f.FileInfo() // Check size. if fi.Size() < MinSize { - zlog.Debug(ctx).Str("member", name).Msg("not actually a jar: too small") + slog.DebugContext(ctx, "not actually a jar: too small", "member", name) return nil } rc, err := f.Open() @@ -286,10 +275,7 @@ func extractInner(ctx context.Context, p srcPath, z *zip.Reader) ([]Info, error) // opening malformed zips. fallthrough case errors.Is(err, zip.ErrFormat): - zlog.Debug(ctx). - Str("member", name). - Err(err). - Msg("not actually a jar: invalid zip") + slog.DebugContext(ctx, "not actually a jar: invalid zip", "member", name) return nil default: return mkErr("failed opening inner zip", err) @@ -302,10 +288,7 @@ func extractInner(ctx context.Context, p srcPath, z *zip.Reader) ([]Info, error) case errors.Is(err, nil): case errors.Is(err, ErrNotAJar) || errors.Is(err, errInsaneManifest): - zlog.Debug(ctx). - Str("member", name). - Err(err). - Msg("not actually a jar") + slog.DebugContext(ctx, "not actually a jar", "reason", err, "member", name) return nil default: return mkErr("parse error", err) @@ -326,8 +309,7 @@ func extractInner(ctx context.Context, p srcPath, z *zip.Reader) ([]Info, error) } if len(ret) == 0 { - zlog.Debug(ctx). - Msg("found no bundled jars") + slog.DebugContext(ctx, "found no bundled jars") } return ret, nil } @@ -347,8 +329,7 @@ var nameRegexp = regexp.MustCompile(`([[:graph:]]+)-([[:digit:]][\-.[:alnum:]]*( func checkName(ctx context.Context, name string) (Info, error) { m := nameRegexp.FindStringSubmatch(filepath.Base(name)) if m == nil { - zlog.Debug(ctx). - Msg("name not useful") + slog.DebugContext(ctx, "name not useful") return Info{}, errUnpopulated } return Info{ @@ -414,26 +395,20 @@ func (i *Info) parseManifest(ctx context.Context, r io.Reader) error { tp := textproto.NewReader(bufio.NewReader(newMainSectionReader(r))) hdr, err := tp.ReadMIMEHeader() if err != nil { - zlog.Debug(ctx). - Err(err). - Msg("unable to read manifest") + slog.DebugContext(ctx, "unable to read manifest", "reason", err) return errInsaneManifest } // Sanity checks: switch { case len(hdr) == 0: - zlog.Debug(ctx). - Msg("no headers found") + slog.DebugContext(ctx, "no headers found") return errInsaneManifest case !manifestVer.MatchString(hdr.Get("Manifest-Version")): v := hdr.Get("Manifest-Version") - zlog.Debug(ctx). - Str("manifest_version", v). - Msg("invalid manifest version") + slog.DebugContext(ctx, "invalid manifest version", "manifest_version", v) return errInsaneManifest case hdr.Get("Name") != "": - zlog.Debug(ctx). - Msg("martian manifest") + slog.DebugContext(ctx, "martian manifest") // This shouldn't be happening in the Main section. return errInsaneManifest } @@ -494,9 +469,8 @@ func (i *Info) parseManifest(ctx context.Context, r io.Reader) error { } if name == "" || version == "" { - zlog.Debug(ctx). - Strs("attrs", []string{name, version}). - Msg("manifest not useful") + slog.DebugContext(ctx, "manifest not useful", + slog.Group("attrs", "name", name, "version", version)) return errUnpopulated } i.Name = name @@ -640,9 +614,8 @@ func (i *Info) parseProperties(ctx context.Context, r io.Reader) error { return mkErr("properties scanner", err) } if group == "" || artifact == "" || version == "" { - zlog.Debug(ctx). - Strs("attrs", []string{group, artifact, version}). - Msg("properties not useful") + slog.DebugContext(ctx, "properties not useful", + slog.Group("attrs", "group", group, "artifact", artifact, "version", version)) return errUnpopulated } diff --git a/java/jar/jar_test.go b/java/jar/jar_test.go index 89e5eb8b2..47e43ebd9 100644 --- a/java/jar/jar_test.go +++ b/java/jar/jar_test.go @@ -5,7 +5,6 @@ import ( "archive/zip" "bytes" "compress/gzip" - "context" "crypto/sha256" "encoding/binary" "encoding/hex" @@ -21,7 +20,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/quay/zlog" "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" @@ -31,7 +29,6 @@ import ( func TestParse(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) const url = `https://repo1.maven.org/maven2/com/orientechnologies/orientdb-community/3.2.37/orientdb-community-3.2.37.tar.gz` const sha = `101d93340ae17cfdc622ef37e30c8c3993874ab199fd5ff3fc76d466740fefe3` name := fetch(t, url, sha) @@ -55,7 +52,7 @@ func TestParse(t *testing.T) { } t.Log("found jar:", h.Name) t.Run(filepath.Base(h.Name), func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) buf.Reset() buf.Grow(int(h.Size)) n, err := io.Copy(&buf, tr) @@ -89,7 +86,7 @@ func TestParse(t *testing.T) { func TestWAR(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) const url = `https://get.jenkins.io/war/2.311/jenkins.war` const sha = `fe21501800c769279699ecf511fd9b495b1cb3ebd226452e01553ff06820910a` name := fetch(t, url, sha) @@ -174,7 +171,6 @@ func fetch(t testing.TB, u string, ck string) (name string) { } func TestJAR(t *testing.T) { - ctx := context.Background() td := os.DirFS("testdata/jar") ls, err := fs.ReadDir(td, ".") if err != nil { @@ -194,7 +190,7 @@ func TestJAR(t *testing.T) { continue } t.Run(n, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f, err := td.Open(ent.Name()) if err != nil { t.Error(err) @@ -232,7 +228,6 @@ func TestJAR(t *testing.T) { } func TestJARBadManifest(t *testing.T) { - ctx := context.Background() path := "testdata/malformed-manifests" d := os.DirFS(path) ls, err := fs.ReadDir(d, ".") @@ -246,7 +241,7 @@ func TestJARBadManifest(t *testing.T) { for _, n := range ls { t.Log(n) t.Run(n.Name(), func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f, err := os.Open(filepath.Join(path, n.Name())) if err != nil { t.Fatal(err) @@ -265,7 +260,6 @@ func TestJARBadManifest(t *testing.T) { // them gracefully. func TestMalformed(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) t.Run("BadOffset", func(t *testing.T) { const ( @@ -327,6 +321,7 @@ func TestMalformed(t *testing.T) { if err != nil { t.Fatal(err) } + ctx := test.Logging(t) infos, err := Parse(ctx, jarName, z) t.Logf("returned error: %v", err) switch { @@ -426,7 +421,6 @@ func TestMalformed(t *testing.T) { t.Fail() } }) - } func TestManifestSectionReader(t *testing.T) { @@ -487,7 +481,7 @@ func TestInnerJar(t *testing.T) { } }) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) got, err := Parse(ctx, name, &rc.Reader) if err != nil { t.Fatal(err) diff --git a/java/jar/manifest_test.go b/java/jar/manifest_test.go index 45affe801..c7f1446c9 100644 --- a/java/jar/manifest_test.go +++ b/java/jar/manifest_test.go @@ -2,7 +2,6 @@ package jar import ( "bytes" - "context" "errors" "io" "io/fs" @@ -11,12 +10,12 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) func TestParseManifest(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) md := os.DirFS("testdata/manifest") fs, err := fs.ReadDir(md, ".") @@ -49,7 +48,7 @@ func TestParseManifest(t *testing.T) { func TestParseManifest_JenkinsPlugins(t *testing.T) { var i Info - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) for _, tc := range jenkinsPlugins { t.Run(tc.Name, func(t *testing.T) { err := i.parseManifest(ctx, strings.NewReader(tc.Contents)) diff --git a/java/jar/name_test.go b/java/jar/name_test.go index e3ef3f504..33d1fb484 100644 --- a/java/jar/name_test.go +++ b/java/jar/name_test.go @@ -1,18 +1,17 @@ package jar import ( - "context" "errors" "io/fs" "os" "testing" - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) func TestCheckName(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) ms, err := fs.Glob(os.DirFS("testdata"), "*/*.jar") if err != nil { diff --git a/java/jar/properties_test.go b/java/jar/properties_test.go index db0ed88f7..a7b2d19e7 100644 --- a/java/jar/properties_test.go +++ b/java/jar/properties_test.go @@ -2,18 +2,17 @@ package jar import ( "bytes" - "context" "io" "io/fs" "os" "testing" - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) func TestParseProperties(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) md := os.DirFS("testdata/properties") fs, err := fs.ReadDir(md, ".") diff --git a/java/matcher.go b/java/matcher.go index fedfdf308..9b96f45c1 100644 --- a/java/matcher.go +++ b/java/matcher.go @@ -2,10 +2,9 @@ package java import ( "context" + "log/slog" "net/url" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/internal/maven" "github.com/quay/claircore/libvuln/driver" @@ -53,10 +52,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v if introduced != "" { iv, err := maven.ParseVersion(introduced) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", introduced). - Msg("unable to parse maven introduced version") + slog.WarnContext(ctx, "unable to parse maven introduced version", + "package", vuln.Package.Name, + "version", introduced) return false, err } // If the package's version is less than the introduced version, it's not vulnerable. @@ -71,10 +69,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v case fixedVersion != "": fv, err := maven.ParseVersion(fixedVersion) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", fixedVersion). - Msg("unable to parse maven fixed version") + slog.WarnContext(ctx, "unable to parse maven fixed version", + "package", vuln.Package.Name, + "version", fixedVersion) return false, err } // The package is affected if its version is less than the fixed version. @@ -82,10 +79,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v case lastAffected != "": la, err := maven.ParseVersion(lastAffected) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", lastAffected). - Msg("unable to parse maven last_affected version") + slog.WarnContext(ctx, "unable to parse maven last_affected version", + "package", vuln.Package.Name, + "version", lastAffected) return false, err } // The package is affected if its version is less than or equal to the last affected version. diff --git a/java/matcher_test.go b/java/matcher_test.go index 026138c8a..05859fb2f 100644 --- a/java/matcher_test.go +++ b/java/matcher_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" @@ -204,5 +203,5 @@ func TestVulnerable(t *testing.T) { } func TestMatcher(t *testing.T) { - test.RunMatcherTests(zlog.Test(context.Background(), t), t, "testdata/matcher", new(Matcher)) + test.RunMatcherTests(test.Logging(t), t, "testdata/matcher", new(Matcher)) } diff --git a/java/packagescanner.go b/java/packagescanner.go index 457cc1cbd..eeba37458 100644 --- a/java/packagescanner.go +++ b/java/packagescanner.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "runtime/trace" @@ -19,8 +20,6 @@ import ( "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/java/jar" @@ -82,9 +81,6 @@ func (*Scanner) Kind() string { return "package" } // Configure implements indexer.RPCScanner. func (s *Scanner) Configure(ctx context.Context, f indexer.ConfigDeserializer, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, - "component", "java/Scanner.Configure", - "version", s.Version()) var cfg ScannerConfig s.client = c if err := f(&cfg); err != nil { @@ -92,7 +88,7 @@ func (s *Scanner) Configure(ctx context.Context, f indexer.ConfigDeserializer, c } if cfg.DisableAPI { - zlog.Debug(ctx).Msg("search API disabled") + slog.DebugContext(ctx, "search API disabled") } else { api := DefaultSearchAPI if cfg.API != "" { @@ -103,10 +99,9 @@ func (s *Scanner) Configure(ctx context.Context, f indexer.ConfigDeserializer, c requestTimeout = cfg.APIRequestTimeout } s.rootRequestTimeout = requestTimeout - zlog.Debug(ctx). - Str("api", api). - Float64("requestTimeout", requestTimeout.Seconds()). - Msg("configured search API URL") + slog.DebugContext(ctx, "configured search API URL", + "api", api, + "requestTimeout", requestTimeout) u, err := url.Parse(api) if err != nil { return err @@ -124,12 +119,8 @@ func (s *Scanner) Configure(ctx context.Context, f indexer.ConfigDeserializer, c func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore.Package, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "java/Scanner.Scan", - "version", s.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") if err := ctx.Err(); err != nil { return nil, err } @@ -154,11 +145,9 @@ func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircor return nil, fmt.Errorf("java: unable to check RPM db: %w", err) } for _, n := range ars { - ctx := zlog.ContextWithValues(ctx, "file", n) + log := slog.With("path", n) if set.Contains(n) { - zlog.Debug(ctx). - Str("path", n). - Msg("file path determined to be of RPM origin") + log.DebugContext(ctx, "file path determined to be of RPM origin") continue } @@ -192,9 +181,7 @@ func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircor // opening malformed zips. fallthrough case errors.Is(err, zip.ErrFormat): - zlog.Info(ctx). - Err(err). - Msg("not actually a jar: invalid zip") + log.InfoContext(ctx, "not actually a jar: invalid zip", "reason", err) continue default: return nil, err @@ -205,9 +192,7 @@ func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircor case err == nil: case errors.Is(err, jar.ErrNotAJar): // Could not prove this is really a jar. Skip it and move on. - zlog.Info(ctx). - AnErr("reason", err). - Msg("skipping jar") + log.InfoContext(ctx, "skipping jar", "reason", err) continue default: return nil, err @@ -301,9 +286,7 @@ func (s *Scanner) search(ctx context.Context, i *jar.Info, ck []byte) error { defer done() req, err := http.NewRequestWithContext(tctx, http.MethodGet, s.root.String(), nil) if err != nil { - zlog.Warn(ctx). - Err(err). - Msg("unable to construct request") + slog.WarnContext(ctx, "unable to construct request", "reason", err) return errRPC } v := req.URL.Query() @@ -314,30 +297,24 @@ func (s *Scanner) search(ctx context.Context, i *jar.Info, ck []byte) error { req.URL.RawQuery = v.Encode() res, err := s.client.Do(req) if err != nil { - zlog.Warn(ctx). - Err(err). - Msg("error making request") + slog.WarnContext(ctx, "error making request", "reason", err) return errRPC } if res.StatusCode != http.StatusOK { res.Body.Close() - zlog.Warn(ctx). - Str("status", res.Status). - Msg("unexpected response status") + slog.WarnContext(ctx, "unexpected response status", "status", res.Status) return errRPC } var sr searchResponse err = json.NewDecoder(res.Body).Decode(&sr) res.Body.Close() if err != nil { - zlog.Warn(ctx). - Err(err). - Msg("error decoding json") + slog.WarnContext(ctx, "error decoding json", "reason", err) return errRPC } success = true if len(sr.Response.Doc) == 0 { - zlog.Debug(ctx).Msg("no matching artifacts found") + slog.DebugContext(ctx, "no matching artifacts found") return nil } // Sort and then take the first one, because apparently the same diff --git a/java/packagescanner_test.go b/java/packagescanner_test.go index 4456a9790..04067c315 100644 --- a/java/packagescanner_test.go +++ b/java/packagescanner_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "github.com/quay/zlog" "net/http" "net/http/httptest" "path" @@ -22,8 +21,7 @@ func TestDisableAPI(t *testing.T) { t.Fatal("external http request invoked when none was expected") })) - ctx := context.Background() - ctx = zlog.Test(ctx, t) + ctx := test.Logging(t) scanner := &java.Scanner{} var buf bytes.Buffer cfg := &java.ScannerConfig{ diff --git a/libindex/fetcher.go b/libindex/fetcher.go index d641a03f9..d8c180146 100644 --- a/libindex/fetcher.go +++ b/libindex/fetcher.go @@ -8,13 +8,13 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "os" "runtime" "strings" - "github.com/quay/zlog" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/trace" @@ -154,15 +154,11 @@ func (f closeFunc) Close() error { // Because we know we're the only concurrent call that's dealing with this blob, // we can be a bit more lax. func (a *RemoteFetchArena) fetchFileForCache(ctx context.Context, desc *claircore.LayerDescription) (*os.File, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "libindex/RemoteFetchArena.fetchFileForCache", - "arena", a.root.Name(), - "layer", desc.Digest, - "uri", desc.URI) - ctx, span := tracer.Start(ctx, "RemoteFetchArena.fetchFileForCache") + log := slog.With("arena", a.root, "layer", desc.Digest, "uri", desc.URI) + ctx, span := tracer.Start(ctx, "RemoteFetchArena.fetchUnlinkedFile") defer span.End() span.SetStatus(codes.Error, "") - zlog.Debug(ctx).Msg("layer fetch start") + log.DebugContext(ctx, "layer fetch start") // Validate the layer input. if desc.URI == "" { @@ -215,9 +211,7 @@ func (a *RemoteFetchArena) fetchFileForCache(ctx context.Context, desc *claircor defer zr.Close() // Look at the content-type and optionally fix it up. ct := resp.Header.Get("content-type") - zlog.Debug(ctx). - Str("content-type", ct). - Msg("reported content-type") + log.DebugContext(ctx, "reported content-type", "content-type", ct) span.SetAttributes(attribute.String("payload.content-type", ct), attribute.Stringer("payload.compression.detected", kind)) if ct == "" || ct == "text/plain" || ct == "binary/octet-stream" || ct == "application/octet-stream" { switch kind { @@ -230,9 +224,7 @@ func (a *RemoteFetchArena) fetchFileForCache(ctx context.Context, desc *claircor default: return nil, fmt.Errorf("fetcher: disallowed compression kind: %q", kind.String()) } - zlog.Debug(ctx). - Str("content-type", ct). - Msg("fixed content-type") + log.DebugContext(ctx, "fixed content-type", "content-type", ct) span.SetAttributes(attribute.String("payload.content-type.detected", ct)) } @@ -275,18 +267,12 @@ func (a *RemoteFetchArena) fetchFileForCache(ctx context.Context, desc *claircor return } if err := f.Close(); err != nil { - zlog.Warn(ctx). - Err(err). - Msg("error closing spoolfile in error return") + log.WarnContext(ctx, "error closing spoolfile in error return", "reason", err) } }() buf := bufio.NewWriter(f) n, err := io.Copy(buf, zr) - zlog.Debug(ctx). - Int64("size", n). - Bool("big", n >= bigLayerSize). - AnErr("copy_error", err). - Msg("wrote file") + log.DebugContext(ctx, "wrote file", "size", n, "big", n >= bigLayerSize, "copy_error", err) // TODO(hank) Add a metric for "big files" and a histogram for size. if err != nil { return nil, err @@ -301,7 +287,7 @@ func (a *RemoteFetchArena) fetchFileForCache(ctx context.Context, desc *claircor return nil, err } - zlog.Debug(ctx).Msg("layer fetch ok") + log.DebugContext(ctx, "layer fetch ok") span.SetStatus(codes.Ok, "") fileOK = true return f, nil @@ -352,8 +338,6 @@ func (p *FetchProxy) Realize(ctx context.Context, ls []*claircore.Layer) error { // RealizeDescriptions returns [claircore.Layer] structs populated according to // the passed slice of [claircore.LayerDescription]. func (p *FetchProxy) RealizeDescriptions(ctx context.Context, descs []claircore.LayerDescription) ([]claircore.Layer, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "libindex/FetchProxy.RealizeDescriptions") ctx, span := tracer.Start(ctx, "RealizeDescriptions") defer span.End() g, ctx := errgroup.WithContext(ctx) diff --git a/libindex/fetcher_test.go b/libindex/fetcher_test.go index 03375ccd6..00e763ea3 100644 --- a/libindex/fetcher_test.go +++ b/libindex/fetcher_test.go @@ -16,8 +16,6 @@ import ( "sync/atomic" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/internal/wart" "github.com/quay/claircore/test" @@ -29,7 +27,7 @@ type fetchTestcase struct { func (tc fetchTestcase) Run(ctx context.Context) func(*testing.T) { return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) c, descs := test.ServeLayers(t, tc.N) for _, l := range descs { t.Logf("%+v", l) @@ -65,7 +63,6 @@ func TestFetchSimple(t *testing.T) { func TestFetchInvalid(t *testing.T) { // TODO(hank) Rewrite this into unified testcases. - ctx := context.Background() tt := []struct { name string layer []*claircore.Layer @@ -91,7 +88,7 @@ func TestFetchInvalid(t *testing.T) { tmp := t.TempDir() for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) a := NewRemoteFetchArena(http.DefaultClient, tmp) fetcher := a.Realizer(ctx) if err := fetcher.Realize(ctx, table.layer); err == nil { @@ -103,7 +100,7 @@ func TestFetchInvalid(t *testing.T) { func TestFetchConcurrent(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) descs, h := commonLayerServer(t, 25) srv := httptest.NewUnstartedServer(h) srv.Start() @@ -119,8 +116,6 @@ func TestFetchConcurrent(t *testing.T) { }) t.Run("OldInterface", func(t *testing.T) { - ctx := zlog.Test(ctx, t) - t.Run("Thread", func(t *testing.T) { run := func(a *RemoteFetchArena, ls []claircore.LayerDescription) func(*testing.T) { ps := wart.DescriptionsToLayers(ls) @@ -132,7 +127,7 @@ func TestFetchConcurrent(t *testing.T) { }) return func(t *testing.T) { t.Parallel() - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f := a.Realizer(ctx) t.Cleanup(func() { if err := f.Close(); err != nil { @@ -151,7 +146,6 @@ func TestFetchConcurrent(t *testing.T) { }) t.Run("NewInterface", func(t *testing.T) { - ctx := zlog.Test(ctx, t) t.Run("Thread", func(t *testing.T) { run := func(a *RemoteFetchArena, descs []claircore.LayerDescription) func(*testing.T) { ds := make([]claircore.LayerDescription, len(descs)) @@ -164,7 +158,7 @@ func TestFetchConcurrent(t *testing.T) { }) return func(t *testing.T) { t.Parallel() - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f := a.Realizer(ctx).(*FetchProxy) defer func() { if err := f.Close(); err != nil { @@ -239,7 +233,6 @@ func commonLayerServer(t testing.TB, ct int) ([]claircore.LayerDescription, http case total < max: t.Logf("prevented %[3]d fetches: %[1]d < %d", total, max, max-total) } - }) inner := http.FileServer(http.Dir(dir)) return descs, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/libindex/libindex.go b/libindex/libindex.go index 117d06d4f..ffd65364a 100644 --- a/libindex/libindex.go +++ b/libindex/libindex.go @@ -7,11 +7,11 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "sort" "time" - "github.com/quay/zlog" "golang.org/x/sync/errgroup" "github.com/quay/claircore" @@ -27,6 +27,7 @@ import ( "github.com/quay/claircore/rhel/rhcc" "github.com/quay/claircore/rpm" "github.com/quay/claircore/ruby" + "github.com/quay/claircore/toolkit/log" "github.com/quay/claircore/whiteout" ) @@ -70,7 +71,6 @@ type Libindex struct { // The passed http.Client will be used for fetching layers and any HTTP requests // made by scanners. func New(ctx context.Context, opts *Options, cl *http.Client) (*Libindex, error) { - ctx = zlog.ContextWithValues(ctx, "component", "libindex/New") // required if opts.Locker == nil { return nil, fmt.Errorf("field Locker cannot be nil") @@ -142,7 +142,7 @@ func New(ctx context.Context, opts *Options, cl *http.Client) (*Libindex, error) return nil, fmt.Errorf("failed to set the indexer state: %v", err) } - zlog.Info(ctx).Msg("registered configured scanners") + slog.InfoContext(ctx, "registered configured scanners") l.vscnrs = vscnrs // create indexer.Options @@ -176,13 +176,11 @@ func (l *Libindex) Close(ctx context.Context) error { // If the index operation cannot start an error will be returned. // If an error occurs during scan the error will be propagated inside the IndexReport. func (l *Libindex) Index(ctx context.Context, manifest *claircore.Manifest) (*claircore.IndexReport, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "libindex/Libindex.Index", - "manifest", manifest.Hash.String()) - zlog.Info(ctx).Msg("index request start") - defer zlog.Info(ctx).Msg("index request done") + ctx = log.With(ctx, "manifest", manifest.Hash) + slog.InfoContext(ctx, "index request start") + defer slog.InfoContext(ctx, "index request done") - zlog.Debug(ctx).Msg("locking attempt") + slog.DebugContext(ctx, "locking attempt") lc, done := l.locker.Lock(ctx, manifest.Hash.String()) defer done() // The process may have waited on the lock, so check that the context is @@ -190,7 +188,7 @@ func (l *Libindex) Index(ctx context.Context, manifest *claircore.Manifest) (*cl if err := lc.Err(); !errors.Is(err, nil) { return nil, err } - zlog.Debug(ctx).Msg("locking OK") + slog.DebugContext(ctx, "locking OK") c := l.ControllerFactory(l.indexerOptions) return c.Index(lc, manifest) } @@ -242,7 +240,6 @@ func (l *Libindex) IndexReport(ctx context.Context, hash claircore.Digest) (*cla // AffectedManifests retrieves a list of affected manifests when provided a list of vulnerabilities. func (l *Libindex) AffectedManifests(ctx context.Context, vulns []claircore.Vulnerability) (*claircore.AffectedManifests, error) { - ctx = zlog.ContextWithValues(ctx, "component", "libindex/Libindex.AffectedManifests") om := omnimatcher.New(nil) affected := claircore.NewAffectedManifests() @@ -285,6 +282,5 @@ V: // // Providing an unknown digest is not an error. func (l *Libindex) DeleteManifests(ctx context.Context, d ...claircore.Digest) ([]claircore.Digest, error) { - ctx = zlog.ContextWithValues(ctx, "component", "libindex/Libindex.DeleteManifests") return l.store.DeleteManifests(ctx, d...) } diff --git a/libindex/libindex_integration_test.go b/libindex/libindex_integration_test.go index 3441d4906..99230be17 100644 --- a/libindex/libindex_integration_test.go +++ b/libindex/libindex_integration_test.go @@ -12,7 +12,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/jackc/pgx/v5/pgxpool" - "github.com/quay/zlog" "go.uber.org/mock/gomock" "github.com/quay/claircore" @@ -157,7 +156,7 @@ func (tc testcase) Run(ctx context.Context, check checkFunc) func(*testing.T) { return func(t *testing.T) { t.Parallel() integration.NeedDB(t) - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) pool := pgtest.TestIndexerDB(ctx, t) tc.RunInner(ctx, t, pool, check) } diff --git a/libindex/libindex_test.go b/libindex/libindex_test.go index 35ff67dce..b1fa99571 100644 --- a/libindex/libindex_test.go +++ b/libindex/libindex_test.go @@ -8,10 +8,10 @@ import ( "strconv" "testing" - "github.com/quay/zlog" "go.uber.org/mock/gomock" "github.com/quay/claircore" + "github.com/quay/claircore/test" indexer "github.com/quay/claircore/test/mock/indexer" ) @@ -45,7 +45,6 @@ func digest(inp string) claircore.Digest { } func TestAffectedManifests(t *testing.T) { - ctx := context.Background() tt := []struct { name string inputVulns []claircore.Vulnerability @@ -94,7 +93,7 @@ func TestAffectedManifests(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) s := table.mockStore(t) li := &Libindex{store: s} @@ -115,7 +114,7 @@ func TestAffectedManifests(t *testing.T) { t.Run("CancelledContext", func(t *testing.T) { for _, table := range tt { t.Run(table.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) ctx, cancel := context.WithCancelCause(ctx) want := errors.New("early cancel") cancel(want) @@ -138,7 +137,6 @@ func TestAffectedManifests(t *testing.T) { } func BenchmarkAffectedManifests(b *testing.B) { - ctx := context.Background() // create store ctrl := gomock.NewController(b) s := indexer.NewMockStore(ctrl) @@ -151,7 +149,7 @@ func BenchmarkAffectedManifests(b *testing.B) { nil, ).MaxTimes(100 * b.N) - ctx = zlog.Test(ctx, b) + ctx := test.Logging(b) li := &Libindex{store: s} for b.Loop() { diff --git a/libvuln/libvuln.go b/libvuln/libvuln.go index e7119297d..65f07ffae 100644 --- a/libvuln/libvuln.go +++ b/libvuln/libvuln.go @@ -3,13 +3,12 @@ package libvuln import ( "context" "fmt" + "log/slog" "math/rand" "reflect" "time" "github.com/google/uuid" - "github.com/quay/zlog" - "github.com/rs/zerolog" "github.com/quay/claircore" "github.com/quay/claircore/datastore" @@ -33,7 +32,6 @@ type Libvuln struct { updaters *updates.Manager } -// TODO (crozzy): Find a home for this and stop redefining it. // LockSource abstracts over how locks are implemented. // // An online system needs distributed locks, offline use cases can use @@ -44,10 +42,10 @@ type LockSource interface { Close(context.Context) error } +// TODO (crozzy): Find a home for this and stop redefining it. + // New creates a new instance of the Libvuln library func New(ctx context.Context, opts *Options) (*Libvuln, error) { - ctx = zlog.ContextWithValues(ctx, "component", "libvuln/New") - // required if opts.Store == nil { return nil, fmt.Errorf("libvuln: must provide a Store") @@ -97,7 +95,7 @@ func New(ctx context.Context, opts *Options) (*Libvuln, error) { return nil, err } - zlog.Info(ctx).Array("matchers", matcherLog(l.matchers)).Msg("matchers created") + slog.InfoContext(ctx, "matchers created", "matcher", matcherLog(l.matchers)) l.updaters, err = updates.NewManager(ctx, l.store, @@ -119,7 +117,7 @@ func New(ctx context.Context, opts *Options) (*Libvuln, error) { go l.updaters.Start(ctx) } - zlog.Info(ctx).Msg("libvuln initialized") + slog.InfoContext(ctx, "libvuln initialized") return l, nil } @@ -224,11 +222,12 @@ func (l *Libvuln) Initialized(ctx context.Context) (bool, error) { // generated documentation URL. type matcherLog []driver.Matcher -func (l matcherLog) MarshalZerologArray(a *zerolog.Array) { - for _, m := range l { +func (l matcherLog) LogValue() slog.Value { + as := make([]slog.Attr, len(l)) + for i, m := range l { t := reflect.ValueOf(m).Elem().Type() - a.Dict(zerolog.Dict(). - Str("name", m.Name()). - Str("docs", `https://pkg.go.dev/`+t.PkgPath())) + as[i] = slog.String(m.Name(), `https://pkg.go.dev/`+t.PkgPath()) } + + return slog.GroupValue(as...) } diff --git a/libvuln/libvuln_test.go b/libvuln/libvuln_test.go deleted file mode 100644 index a19cde3c9..000000000 --- a/libvuln/libvuln_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package libvuln - -import ( - "bytes" - "context" - "testing" - - "github.com/rs/zerolog" - - "github.com/quay/claircore" - "github.com/quay/claircore/libvuln/driver" -) - -func TestMatcherLog(t *testing.T) { - const want = `{"matchers":[{"name":"test-matcher","docs":"https://pkg.go.dev/github.com/quay/claircore/libvuln"}]}` + "\n" - var buf bytes.Buffer - log := zerolog.New(&buf) - log.Log().Array("matchers", matcherLog([]driver.Matcher{&TestMatcher{}})).Send() - - got := buf.String() - t.Logf("got: %+#q", got) - if got != want { - t.Errorf("want: %+#q", want) - } -} - -// Helper for above test -type TestMatcher struct{} - -var _ driver.Matcher = (*TestMatcher)(nil) - -func (*TestMatcher) Name() string { - return "test-matcher" -} - -func (*TestMatcher) Filter(*claircore.IndexRecord) bool { - return false -} - -func (*TestMatcher) Query() []driver.MatchConstraint { - return nil -} - -func (*TestMatcher) Vulnerable(context.Context, *claircore.IndexRecord, *claircore.Vulnerability) (bool, error) { - return false, nil -} diff --git a/libvuln/updates.go b/libvuln/updates.go index 57e5a0c3c..94c94533e 100644 --- a/libvuln/updates.go +++ b/libvuln/updates.go @@ -4,10 +4,10 @@ import ( "context" "fmt" "io" + "log/slog" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgxpool" - "github.com/quay/zlog" "github.com/quay/claircore/datastore/postgres" "github.com/quay/claircore/libvuln/driver" @@ -23,8 +23,6 @@ func OfflineImport(ctx context.Context, pool *pgxpool.Pool, in io.Reader) error // BUG(hank) The OfflineImport function is a wart, needed to work around // some package namespacing issues. It should get refactored if claircore // gets merged into clair. - ctx = zlog.ContextWithValues(ctx, "component", "libvuln/OfflineImporter") - s := postgres.NewMatcherStore(pool) l, err := jsonblob.Load(ctx, in) if err != nil { @@ -39,13 +37,12 @@ func OfflineImport(ctx context.Context, pool *pgxpool.Pool, in io.Reader) error Update: for l.Next() { e := l.Entry() + log := slog.With("updater", e.Updater) for _, op := range ops[e.Updater] { // This only helps if updaters don't keep something that // changes in the fingerprint. if op.Fingerprint == e.Fingerprint { - zlog.Info(ctx). - Str("updater", e.Updater). - Msg("fingerprint match, skipping") + log.InfoContext(ctx, "fingerprint match, skipping") continue Update } } @@ -60,12 +57,10 @@ Update: return fmt.Errorf("updating vulnerabilities: %w", err) } } - zlog.Info(ctx). - Str("updater", e.Updater). - Str("ref", ref.String()). - Int("vuln_count", len(e.Vuln)). - Int("enrichment_count", len(e.Enrichment)). - Msg("update imported") + log.InfoContext(ctx, "update imported", + "ref", ref, + "vuln_count", len(e.Vuln), + "enrichment_count", len(e.Enrichment)) } if err := l.Err(); err != nil { return err diff --git a/libvuln/updates/manager.go b/libvuln/updates/manager.go index e54ad2edc..770077180 100644 --- a/libvuln/updates/manager.go +++ b/libvuln/updates/manager.go @@ -5,13 +5,13 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "runtime" "strings" "time" "github.com/google/uuid" - "github.com/quay/zlog" "golang.org/x/sync/semaphore" "github.com/quay/claircore" @@ -62,8 +62,6 @@ type Manager struct { // NewManager will return a manager ready to have its Start or Run methods called. func NewManager(ctx context.Context, store datastore.Updater, locks LockSource, client *http.Client, opts ...ManagerOption) (*Manager, error) { - ctx = zlog.ContextWithValues(ctx, "component", "libvuln/updates/NewManager") - // the default Manager m := &Manager{ store: store, @@ -98,21 +96,19 @@ func NewManager(ctx context.Context, store datastore.Updater, locks LockSource, // // Start must only be called once between context cancellations. func (m *Manager) Start(ctx context.Context) error { - ctx = zlog.ContextWithValues(ctx, "component", "libvuln/updates/Manager.Start") - if m.interval == 0 { return fmt.Errorf("manager must be configured with an interval to start") } // perform the initial run - zlog.Info(ctx).Msg("starting initial updates") + slog.InfoContext(ctx, "starting initial updates") err := m.Run(ctx) if err != nil { - zlog.Error(ctx).Err(err).Msg("errors encountered during updater run") + slog.ErrorContext(ctx, "errors encountered during updater run", "reason", err) } // perform run on every tick - zlog.Info(ctx).Str("interval", m.interval.String()).Msg("starting background updates") + slog.InfoContext(ctx, "starting background updates", "interval", m.interval) t := time.NewTicker(m.interval) defer t.Stop() for { @@ -122,7 +118,7 @@ func (m *Manager) Start(ctx context.Context) error { case <-t.C: err := m.Run(ctx) if err != nil { - zlog.Error(ctx).Err(err).Msg("errors encountered during updater run") + slog.ErrorContext(ctx, "errors encountered during updater run", "reason", err) } } } @@ -134,8 +130,6 @@ func (m *Manager) Start(ctx context.Context) error { // Run is safe to call at anytime, regardless of whether background updaters // are running. func (m *Manager) Run(ctx context.Context) error { - ctx = zlog.ContextWithValues(ctx, "component", "libvuln/updates/Manager.Run") - updaters := []driver.Updater{} // Constructing updater sets may require network access // depending on the factory. @@ -145,23 +139,21 @@ func (m *Manager) Run(ctx context.Context) error { updateTime := time.Now() set, err := factory.UpdaterSet(ctx) if err != nil { - zlog.Error(ctx).Err(err).Msg("failed constructing factory, excluding from run") + slog.ErrorContext(ctx, "failed constructing factory, excluding from run", "reason", err) continue } if stubUpdaterInSet(set) { updaterSetName, err := getFactoryNameFromStubUpdater(set) if err != nil { - zlog.Error(ctx). - Err(err). - Msg("error getting updater set name") + slog.ErrorContext(ctx, "error getting updater set name", + "reason", err) } err = m.store.RecordUpdaterSetStatus(ctx, updaterSetName, updateTime) if err != nil { - zlog.Error(ctx). - Err(err). - Str("updaterSetName", updaterSetName). - Time("updateTime", updateTime). - Msg("error while recording update success for all updaters in updater set") + slog.ErrorContext(ctx, "error while recording update success for all updaters in updater set", + "updaterSetName", updaterSetName, + "updateTime", updateTime, + "reason", err) } continue } @@ -178,29 +170,25 @@ func (m *Manager) Run(ctx context.Context) error { cfg = noopConfig } if err := f.Configure(ctx, cfg, m.client); err != nil { - zlog.Warn(ctx). - Err(err). - Str("updater", name). - Msg("failed configuring updater, excluding from current run") + slog.WarnContext(ctx, "failed configuring updater, excluding from current run", + "updater", name, + "reason", err) continue } } toRun = append(toRun, u) } - zlog.Info(ctx). - Int("total", len(toRun)). - Int("batchSize", m.batchSize). - Msg("running updaters") + slog.InfoContext(ctx, "running updaters", + "total", len(toRun), + "batchSize", m.batchSize) sem := semaphore.NewWeighted(int64(m.batchSize)) errChan := make(chan error, len(toRun)+1) // +1 for a potential ctx error for i := range toRun { err := sem.Acquire(ctx, 1) if err != nil { - zlog.Error(ctx). - Err(err). - Msg("sem acquire failed, ending updater run") + slog.ErrorContext(ctx, "sem acquire failed, ending updater run", "reason", err) break } @@ -210,10 +198,9 @@ func (m *Manager) Run(ctx context.Context) error { ctx, done := m.locks.TryLock(ctx, u.Name()) defer done() if err := ctx.Err(); err != nil { - zlog.Debug(ctx). - Err(err). - Str("updater", u.Name()). - Msg("lock context canceled, excluding from run") + slog.DebugContext(ctx, "lock context canceled, excluding from run", + "reason", err, + "updater", u.Name()) return } @@ -232,19 +219,16 @@ func (m *Manager) Run(ctx context.Context) error { if m.updateRetention != 0 { ctx, done := m.locks.TryLock(ctx, "garbage-collection") if err := ctx.Err(); err != nil { - zlog.Debug(ctx). - Err(err). - Msg("lock context canceled, garbage collection already running") + slog.DebugContext(ctx, "lock context canceled, garbage collection already running", "reason", err) } else { - zlog.Info(ctx).Int("retention", m.updateRetention).Msg("GC started") + slog.InfoContext(ctx, "GC started", "retention", m.updateRetention) i, err := m.store.GC(ctx, m.updateRetention) if err != nil { - zlog.Error(ctx).Err(err).Msg("error while performing GC") + slog.ErrorContext(ctx, "error while performing GC", "reason", err) } else { - zlog.Info(ctx). - Int64("remaining_ops", i). - Int("retention", m.updateRetention). - Msg("GC completed") + slog.InfoContext(ctx, "GC completed", + "remaining_ops", i, + "retention", m.updateRetention) } } done() @@ -286,36 +270,30 @@ func getFactoryNameFromStubUpdater(set driver.UpdaterSet) (string, error) { func (m *Manager) driveUpdater(ctx context.Context, u driver.Updater) (err error) { var newFP driver.Fingerprint updateTime := time.Now() + name := u.Name() + log := slog.With("updater", name) defer func() { - deferErr := m.store.RecordUpdaterStatus(ctx, u.Name(), updateTime, newFP, err) + deferErr := m.store.RecordUpdaterStatus(ctx, name, updateTime, newFP, err) if deferErr != nil { - zlog.Error(ctx). - Err(deferErr). - Str("updater", u.Name()). - Time("updateTime", updateTime). - Msg("error while recording updater status") + log.ErrorContext(ctx, "error while recording updater status", + "reason", deferErr, + "updateTime", updateTime) } }() - name := u.Name() - ctx = zlog.ContextWithValues(ctx, - "component", "libvuln/updates/Manager.driveUpdater", - "updater", name) - zlog.Info(ctx).Msg("starting update") - defer zlog.Info(ctx).Msg("finished update") + log.InfoContext(ctx, "starting update") + defer log.InfoContext(ctx, "finished update") uoKind := driver.VulnerabilityKind // Do some assertions eu, euOK := u.(driver.EnrichmentUpdater) if euOK { - zlog.Info(ctx). - Msg("found EnrichmentUpdater") + log.InfoContext(ctx, "found EnrichmentUpdater") uoKind = driver.EnrichmentKind } du, duOK := u.(driver.DeltaUpdater) if duOK { - zlog.Info(ctx). - Msg("found DeltaUpdater") + slog.InfoContext(ctx, "found DeltaUpdater") } var prevFP driver.Fingerprint @@ -341,7 +319,7 @@ func (m *Manager) driveUpdater(ctx context.Context, u driver.Updater) (err error switch { case err == nil: case errors.Is(err, driver.Unchanged): - zlog.Info(ctx).Msg("vulnerability database unchanged") + log.InfoContext(ctx, "vulnerability database unchanged") err = nil return default: @@ -386,9 +364,7 @@ func (m *Manager) driveUpdater(ctx context.Context, u driver.Updater) (err error err = fmt.Errorf("failed to update: %v", err) return } - zlog.Info(ctx). - Str("ref", ref.String()). - Msg("successful update") + log.InfoContext(ctx, "successful update", "ref", ref) return nil } diff --git a/libvuln/updates/manager_test.go b/libvuln/updates/manager_test.go index 70e1aa5c5..502b30139 100644 --- a/libvuln/updates/manager_test.go +++ b/libvuln/updates/manager_test.go @@ -12,20 +12,20 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/jackc/pgx/v5/pgxpool" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/datastore/postgres" "github.com/quay/claircore/libvuln/driver" "github.com/quay/claircore/pkg/ctxlock/v2" + "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" pgtest "github.com/quay/claircore/test/postgres" ) func TestDeltaUpdates(t *testing.T) { integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) facs := map[string]driver.UpdaterSetFactory{ "delta": &Factory{ vulnGetter: &vulnGetter{ @@ -81,8 +81,10 @@ func TestDeltaUpdates(t *testing.T) { } } -var _ driver.DeltaUpdater = (*testUpdater)(nil) -var _ driver.Updater = (*testUpdater)(nil) +var ( + _ driver.DeltaUpdater = (*testUpdater)(nil) + _ driver.Updater = (*testUpdater)(nil) +) type testUpdater struct { vulnGetter *vulnGetter diff --git a/linux/coalescer_test.go b/linux/coalescer_test.go index 4a9d84fce..fda4f45e9 100644 --- a/linux/coalescer_test.go +++ b/linux/coalescer_test.go @@ -1,19 +1,16 @@ package linux import ( - "context" "strconv" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/test" ) func TestCoalescer(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) coalescer := &Coalescer{ ir: &claircore.IndexReport{ Environments: map[string][]*claircore.Environment{}, diff --git a/matchers/matchers.go b/matchers/matchers.go index 14e9724d7..333c644e7 100644 --- a/matchers/matchers.go +++ b/matchers/matchers.go @@ -4,10 +4,9 @@ import ( "context" "errors" "fmt" + "log/slog" "net/http" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" _ "github.com/quay/claircore/matchers/defaults" "github.com/quay/claircore/matchers/registry" @@ -30,7 +29,6 @@ type MatchersOption func(m *Matchers) // NewMatchers will return a slice of Matcher created based on the provided // MatchersOption. func NewMatchers(ctx context.Context, client *http.Client, opts ...MatchersOption) ([]driver.Matcher, error) { - ctx = zlog.ContextWithValues(ctx, "component", "libvuln/matchers/NewMatchers") if client == nil { return nil, errors.New("invalid *http.Client") } @@ -57,7 +55,7 @@ func NewMatchers(ctx context.Context, client *http.Client, opts ...MatchersOptio for _, factory := range m.factories { matcher, err := factory.Matcher(ctx) if err != nil { - zlog.Error(ctx).Err(err).Msg("failed constructing factory, excluding from run") + slog.ErrorContext(ctx, "failed constructing factory, excluding from run", "reason", err) continue } matchers = append(matchers, matcher...) diff --git a/nodejs/coalescer_test.go b/nodejs/coalescer_test.go index dba365f03..d8a55a364 100644 --- a/nodejs/coalescer_test.go +++ b/nodejs/coalescer_test.go @@ -1,12 +1,9 @@ package nodejs import ( - "context" "strconv" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/test" @@ -14,7 +11,7 @@ import ( func TestCoalescer(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) coalescer := &coalescer{} pkgs := test.GenUniquePackages(6) repo := []*claircore.Repository{&Repository} diff --git a/nodejs/matcher_test.go b/nodejs/matcher_test.go index 329360d3a..0cd1bd753 100644 --- a/nodejs/matcher_test.go +++ b/nodejs/matcher_test.go @@ -1,15 +1,13 @@ package nodejs import ( - "context" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore/test" ) func TestMatcher(t *testing.T) { t.Parallel() - test.RunMatcherTests(zlog.Test(context.Background(), t), t, "testdata/matcher", new(Matcher)) + ctx := test.Logging(t) + test.RunMatcherTests(ctx, t, "testdata/matcher", new(Matcher)) } diff --git a/nodejs/packagescanner.go b/nodejs/packagescanner.go index 9c56be593..1e0e5af90 100644 --- a/nodejs/packagescanner.go +++ b/nodejs/packagescanner.go @@ -8,12 +8,12 @@ import ( "encoding/json" "fmt" "io/fs" + "log/slog" "path/filepath" "runtime/trace" "strings" "github.com/Masterminds/semver" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -67,12 +67,8 @@ type packageJSON struct { func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore.Package, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "nodejs/Scanner.Scan", - "version", s.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") if err := ctx.Err(); err != nil { return nil, err } @@ -99,9 +95,7 @@ func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircor for _, p := range pkgs { if set.Contains(p) { - zlog.Debug(ctx). - Str("path", p). - Msg("file path determined to be of RPM origin") + slog.DebugContext(ctx, "file path determined to be of RPM origin", "path", p) continue } @@ -128,17 +122,16 @@ func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircor if sv, err := semver.NewVersion(pkgJSON.Version); err == nil { pkg.NormalizedVersion = claircore.FromSemver(sv) } else { - zlog.Info(ctx). - Str("package", pkg.Name). - Str("version", pkg.Version). - Msg("invalid semantic version") + slog.InfoContext(ctx, "invalid semantic version", + "package", pkg.Name, + "version", pkg.Version) } ret = append(ret, pkg) } if len(invalidPkgs) > 0 { - zlog.Debug(ctx).Strs("paths", invalidPkgs).Msg("unable to decode package.json, skipping") + slog.DebugContext(ctx, "unable to decode package.json, skipping", "paths", invalidPkgs) } return ret, nil @@ -146,14 +139,7 @@ func (s *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircor func packages(ctx context.Context, sys fs.FS) (out []string, err error) { return out, fs.WalkDir(sys, ".", func(p string, d fs.DirEntry, err error) error { - ev := zlog.Debug(ctx). - Str("file", p) - var success bool - defer func() { - if !success { - ev.Discard().Send() - } - }() + attrs := []slog.Attr{slog.String("file", p)} switch { case err != nil: return err @@ -168,12 +154,11 @@ func packages(ctx context.Context, sys fs.FS) (out []string, err error) { // for more information. return nil case strings.HasSuffix(p, "/package.json"): - ev = ev.Str("kind", "package.json") + attrs = append(attrs, slog.String("kind", "package.json")) default: return nil } - ev.Msg("found package") - success = true + slog.LogAttrs(ctx, slog.LevelDebug, "found package", attrs...) out = append(out, p) return nil }) diff --git a/nodejs/packagescanner_test.go b/nodejs/packagescanner_test.go index d8aa08ae3..54818cf61 100644 --- a/nodejs/packagescanner_test.go +++ b/nodejs/packagescanner_test.go @@ -7,14 +7,13 @@ import ( "github.com/quay/claircore" "github.com/quay/claircore/nodejs" + "github.com/quay/claircore/test" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" ) func TestScanLocal(t *testing.T) { t.Parallel() - ctx := t.Context() table := []struct { name string @@ -52,7 +51,7 @@ func TestScanLocal(t *testing.T) { } defer file.Close() - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) scanner := &nodejs.Scanner{} var l claircore.Layer err = l.Init(ctx, &claircore.LayerDescription{ diff --git a/oracle/distributionscanner.go b/oracle/distributionscanner.go index fc5446b6b..5c002e620 100644 --- a/oracle/distributionscanner.go +++ b/oracle/distributionscanner.go @@ -3,11 +3,10 @@ package oracle import ( "bytes" "context" + "log/slog" "regexp" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -83,15 +82,11 @@ func (*DistributionScanner) Kind() string { return scannerKind } // If the files are found but all regexp fail to match an empty slice is returned. func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "oracle/DistributionScanner.Scan", - "version", ds.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") files, err := l.Files(osReleasePath, issuePath) if err != nil { - zlog.Debug(ctx).Msg("didn't find an os-release or issues file") + slog.DebugContext(ctx, "didn't find an os-release or issues file") return nil, nil } for _, buff := range files { diff --git a/oracle/parser.go b/oracle/parser.go index 386be1b33..e1b4c2e06 100644 --- a/oracle/parser.go +++ b/oracle/parser.go @@ -5,9 +5,9 @@ import ( "encoding/xml" "fmt" "io" + "log/slog" "github.com/quay/goval-parser/oval" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/internal/xmlutil" @@ -36,8 +36,7 @@ var platformToDist = map[string]*claircore.Distribution{ var _ driver.Parser = (*Updater)(nil) func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "oracle/Updater.Parse") - zlog.Info(ctx).Msg("starting parse") + slog.InfoContext(ctx, "starting parse") defer r.Close() root := oval.Root{} dec := xml.NewDecoder(r) @@ -45,7 +44,7 @@ func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln if err := dec.Decode(&root); err != nil { return nil, fmt.Errorf("oracle: unable to decode OVAL document: %w", err) } - zlog.Debug(ctx).Msg("xml decoded") + slog.DebugContext(ctx, "xml decoded") protoVulns := func(def oval.Definition) ([]*claircore.Vulnerability, error) { // In all oracle databases tested a single // and correct platform string can be found inside a definition @@ -87,10 +86,9 @@ func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln if err != nil { // Found a CPE but could not parse it. Log a warning and return // successfully. - zlog.Warn(ctx). - Str("def_title", def.Title). - Str("cpe", affected). - Msg("could not parse CPE: there may be a false positive match with a userspace_ksplice package") + slog.WarnContext(ctx, "could not parse CPE: there may be a false positive match with a userspace_ksplice package", + "def_title", def.Title, + "cpe", affected) return vs, nil } if wfn.Attr[cpe.Edition].V == "userspace_ksplice" { @@ -102,16 +100,14 @@ func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln case kspliceCPEs == 0: // Continue if there are no ksplice CPEs. case cpes == 0: - zlog.Warn(ctx). - Str("def_title", def.Title). - Msg("potential false positives: couldn't find CPEs to check for ksplice packages") + slog.WarnContext(ctx, "potential false positives: couldn't find CPEs to check for ksplice packages", + "def_title", def.Title) case diff == 0: - zlog.Debug(ctx).Msg("skipping userspace_ksplice vulnerabilities") + slog.DebugContext(ctx, "skipping userspace_ksplice vulnerabilities") return nil, nil case diff > 0: - zlog.Warn(ctx). - Str("def_title", def.Title). - Msg("potential false positives: OVAL may have a userspace_ksplice CPE which could not be skipped") + slog.WarnContext(ctx, "potential false positives: OVAL may have a userspace_ksplice CPE which could not be skipped", + "def_title", def.Title) default: panic("programmer error") } diff --git a/oracle/parser_test.go b/oracle/parser_test.go index b1d5a3e05..34ef0e756 100644 --- a/oracle/parser_test.go +++ b/oracle/parser_test.go @@ -1,16 +1,15 @@ package oracle import ( - "context" "os" "testing" - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) func TestParse(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) u, err := NewUpdater(-1) if err != nil { t.Fatal(err) diff --git a/oracle/updater_test.go b/oracle/updater_test.go index d6cccf304..62a29bc8c 100644 --- a/oracle/updater_test.go +++ b/oracle/updater_test.go @@ -1,18 +1,16 @@ package oracle import ( - "context" "net/http" "net/http/httptest" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" ) func TestFetch(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "testdata/com.oracle.elsa-2018.xml") })) diff --git a/osrelease/scanner.go b/osrelease/scanner.go index c3116511d..041d51752 100644 --- a/osrelease/scanner.go +++ b/osrelease/scanner.go @@ -7,12 +7,12 @@ import ( "context" "fmt" "io" + "log/slog" "runtime/trace" "sort" "strings" "github.com/quay/claircore/toolkit/types/cpe" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -57,12 +57,8 @@ func (*Scanner) Kind() string { return scannerKind } // present in the layer. func (s *Scanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "osrelease/Scanner.Scan", - "version", s.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { @@ -75,10 +71,7 @@ func (s *Scanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Di for _, n := range []string{Path, FallbackPath} { f, err := sys.Open(n) if err != nil { - zlog.Debug(ctx). - Str("name", n). - Err(err). - Msg("unable to open file") + slog.DebugContext(ctx, "unable to open file", "name", n, "reason", err) continue } defer f.Close() @@ -86,7 +79,7 @@ func (s *Scanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Di break } if rd == nil { - zlog.Debug(ctx).Msg("didn't find an os-release file") + slog.DebugContext(ctx, "didn't find an os-release file") return nil, nil } d, err := toDist(ctx, rd) @@ -98,8 +91,6 @@ func (s *Scanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Di // ToDist returns the distribution information from the file contents provided on r. func toDist(ctx context.Context, r io.Reader) (*claircore.Distribution, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "osrelease/parse") defer trace.StartRegion(ctx, "parse").End() m, err := Parse(ctx, r) if err != nil { @@ -115,48 +106,41 @@ func toDist(ctx context.Context, r io.Reader) (*claircore.Distribution, error) { } sort.Strings(ks) for _, key := range ks { + slog.DebugContext(ctx, "found key", "key", key) value := m[key] switch key { case "ID": - zlog.Debug(ctx).Msg("found ID") d.DID = value case "VERSION_ID": - zlog.Debug(ctx).Msg("found VERSION_ID") d.VersionID = value case "BUILD_ID": case "VARIANT_ID": case "CPE_NAME": - zlog.Debug(ctx).Msg("found CPE_NAME") wfn, err := cpe.Unbind(value) if err != nil { - zlog.Warn(ctx). - Err(err). - Str("value", value). - Msg("failed to unbind the cpe") + slog.WarnContext(ctx, "failed to unbind the cpe", "reason", err, "value", value) break } d.CPE = wfn case "NAME": - zlog.Debug(ctx).Msg("found NAME") d.Name = value case "VERSION": - zlog.Debug(ctx).Msg("found VERSION") d.Version = value case "ID_LIKE": case "VERSION_CODENAME": - zlog.Debug(ctx).Msg("found VERISON_CODENAME") d.VersionCodeName = value case "PRETTY_NAME": - zlog.Debug(ctx).Msg("found PRETTY_NAME") d.PrettyName = value case "REDHAT_BUGZILLA_PRODUCT": - zlog.Debug(ctx).Msg("using RHEL hack") + slog.DebugContext(ctx, "using RHEL hack") // This is a dirty hack because the Red Hat OVAL database and the // CPE contained in the os-release file don't agree. d.PrettyName = value + default: + continue } } - zlog.Debug(ctx).Str("name", d.Name).Msg("found dist") + slog.DebugContext(ctx, "found dist", "name", d.Name) return &d, nil } @@ -165,7 +149,6 @@ func toDist(ctx context.Context, r io.Reader) (*claircore.Distribution, error) { // // See comments in the source for edge cases. func Parse(ctx context.Context, r io.Reader) (map[string]string, error) { - ctx = zlog.ContextWithValues(ctx, "component", "osrelease/Parse") defer trace.StartRegion(ctx, "Parse").End() m := make(map[string]string) s := bufio.NewScanner(r) diff --git a/osrelease/scanner_test.go b/osrelease/scanner_test.go index 91e01a18d..5b1c26a8c 100644 --- a/osrelease/scanner_test.go +++ b/osrelease/scanner_test.go @@ -2,14 +2,12 @@ package osrelease import ( "bytes" - "context" "encoding/json" "path/filepath" "strings" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "golang.org/x/tools/txtar" "github.com/quay/claircore" @@ -18,14 +16,13 @@ import ( func TestParse(t *testing.T) { t.Parallel() - ctx := context.Background() ms, _ := filepath.Glob("testdata/*.txtar") for i := range ms { m := ms[i] name := strings.TrimSuffix(filepath.Base(m), ".txtar") t.Run(name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) ar, err := txtar.ParseFile(m) if err != nil { t.Fatal(err) @@ -99,7 +96,7 @@ type layerspec struct { func (lc layercase) Test(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) l := test.RealizeLayer(ctx, t, lc.Layer) var s Scanner diff --git a/photon/distributionscanner.go b/photon/distributionscanner.go index 3d2bb0d27..b6bceae60 100644 --- a/photon/distributionscanner.go +++ b/photon/distributionscanner.go @@ -3,11 +3,10 @@ package photon import ( "bytes" "context" + "log/slog" "regexp" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -74,15 +73,11 @@ func (*DistributionScanner) Kind() string { return scannerKind } // If the files are found but all regexp fail to match an empty slice is returned. func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "photon/DistributionScanner.Scan", - "version", ds.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") files, err := l.Files(osReleasePath, photonReleasePath) if err != nil { - zlog.Debug(ctx).Msg("didn't find an os-release or photon-release") + slog.DebugContext(ctx, "didn't find an os-release or photon-release") return nil, nil } for _, buff := range files { diff --git a/photon/parser.go b/photon/parser.go index 7467b1462..47018fb48 100644 --- a/photon/parser.go +++ b/photon/parser.go @@ -5,9 +5,9 @@ import ( "encoding/xml" "fmt" "io" + "log/slog" "github.com/quay/goval-parser/oval" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/internal/xmlutil" @@ -18,8 +18,7 @@ import ( var _ driver.Parser = (*Updater)(nil) func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "photon/Updater.Parse") - zlog.Info(ctx).Msg("starting parse") + slog.InfoContext(ctx, "starting parse") defer r.Close() root := oval.Root{} dec := xml.NewDecoder(r) @@ -27,11 +26,11 @@ func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln if err := dec.Decode(&root); err != nil { return nil, fmt.Errorf("photon: unable to decode OVAL document: %w", err) } - zlog.Debug(ctx).Msg("xml decoded") + slog.DebugContext(ctx, "xml decoded") protoVulns := func(def oval.Definition) ([]*claircore.Vulnerability, error) { return []*claircore.Vulnerability{ - &claircore.Vulnerability{ + { Updater: u.Name(), Name: def.Title, Description: def.Description, diff --git a/pkg/ctxlock/v2/ctxlock.go b/pkg/ctxlock/v2/ctxlock.go index 503d6116a..3b56b494e 100644 --- a/pkg/ctxlock/v2/ctxlock.go +++ b/pkg/ctxlock/v2/ctxlock.go @@ -8,16 +8,15 @@ import ( "context" "errors" "fmt" + "log/slog" "runtime" "runtime/pprof" "runtime/trace" - "strconv" "sync" "time" "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgxpool" - "github.com/quay/zlog" "github.com/quay/claircore/internal/dblock" ) @@ -93,26 +92,20 @@ var ( func (l *Locker) run(ctx context.Context) { ctx = pprof.WithLabels(ctx, pprof.Labels(tracelabel, `run`)) pprof.SetGoroutineLabels(ctx) - ctx = zlog.ContextWithValues(ctx, "component", "internal/ctxlock/Locker.run") for { tctx, done := context.WithTimeout(ctx, 5*time.Second) err := l.p.AcquireFunc(tctx, l.reconnect(ctx)) done() switch { case errors.Is(err, errExiting): - zlog.Debug(ctx). - Msg("ctxlocker exiting") + slog.DebugContext(ctx, "ctxlocker exiting") return case errors.Is(err, nil): return case errors.Is(err, context.DeadlineExceeded): - zlog.Info(ctx). - Err(err). - Msg("retrying immediately") + slog.InfoContext(ctx, "retrying immediately", "reason", err) default: - zlog.Warn(ctx). - Err(err). - Msg("unexpected error; retrying immediately") + slog.WarnContext(ctx, "unexpected error; retrying immediately", "reason", err) } } } @@ -133,7 +126,6 @@ func (l *Locker) Close(_ context.Context) (_ error) { // itself until awoken. All other methods should strobe the Cond to wake up this // loop and check if the connection has died. func (l *Locker) reconnect(ctx context.Context) func(*pgxpool.Conn) error { - ctx = zlog.ContextWithValues(ctx, "component", "internal/ctxlock/Locker.reconnect") return func(c *pgxpool.Conn) error { l.rc.L.Lock() defer l.rc.L.Unlock() @@ -141,15 +133,15 @@ func (l *Locker) reconnect(ctx context.Context) func(*pgxpool.Conn) error { l.gone = make(chan struct{}) l.cur = make(map[string]struct{}, 100) // Guess at a good capacity. l.gen++ - ctx = zlog.ContextWithValues(ctx, "gen", strconv.Itoa(l.gen)) + log := slog.With(slog.Int("gen", l.gen)) defer func() { close(l.gone) l.gone = nil l.conn = nil l.cur = nil - zlog.Debug(ctx).Msg("torn down") + log.DebugContext(ctx, "torn down") }() - zlog.Debug(ctx).Msg("set up") + log.DebugContext(ctx, "set up") l.rc.Broadcast() for l.gen > 0 { @@ -157,9 +149,7 @@ func (l *Locker) reconnect(ctx context.Context) func(*pgxpool.Conn) error { err := c.Ping(ctx) done() if err != nil { - zlog.Warn(ctx). - Err(err). - Msg("liveness check failed") + log.WarnContext(ctx, "liveness check failed", "reason", err) return err } l.rc.Wait() @@ -183,15 +173,6 @@ func (l *Locker) ping(ctx context.Context) { } } -/* -The TryLock and Lock methods do not add logging baggage, because the additional -allocations around the context.Context really stack up. Ensure that any -additional information is added to the zlog calls directly. - -I've left some Debug logs commented out because zlog needs to gain a level knob -for tests. Currently, the logs always happen and throw off benchmarks. -*/ - // TryLock attempts to lock on the provided key. // // If unsuccessful, an already-canceled Context will be returned. @@ -199,7 +180,8 @@ for tests. Currently, the logs always happen and throw off benchmarks. // If successful, the returned Context will be parented to the passed-in Context // and also to the underlying connection used for the lock. func (l *Locker) TryLock(parent context.Context, key string) (context.Context, context.CancelFunc) { - // zlog.Debug(parent).Str("key", key).Msg("trying lock") + a := slog.String("key", key) + slog.DebugContext(parent, "trying lock", a) defer trace.StartRegion(parent, pkgname+".TryLock").End() child, done := context.WithCancel(parent) w, err := l.try(parent, key, done) @@ -209,14 +191,9 @@ func (l *Locker) TryLock(parent context.Context, key string) (context.Context, c case errors.Is(err, errConnGone) || errors.Is(err, errLockFail) || errors.Is(err, errDoubleLock): - zlog.Debug(parent). - Err(err). - Str("key", key). - Msg("lock failed") + slog.DebugContext(parent, "lock failed", a, "reason", err) default: - zlog.Info(parent). - Err(err). - Msg("checking lock liveness") + slog.InfoContext(parent, "checking lock liveness", a, "reason", err) l.rc.Broadcast() } done() @@ -226,7 +203,8 @@ func (l *Locker) TryLock(parent context.Context, key string) (context.Context, c // Lock attempts to obtain the named lock until it succeeds or the passed // Context is canceled. func (l *Locker) Lock(parent context.Context, key string) (context.Context, context.CancelFunc) { - // zlog.Debug(parent).Str("key", key).Msg("locking") + a := slog.String("key", key) + slog.DebugContext(parent, "locking", a) defer trace.StartRegion(parent, pkgname+".Lock").End() child, done := context.WithCancel(parent) for wait := time.Duration(500 * time.Millisecond); ; backoff(&wait) { @@ -237,14 +215,9 @@ func (l *Locker) Lock(parent context.Context, key string) (context.Context, cont case errors.Is(err, errConnGone) || errors.Is(err, errLockFail) || errors.Is(err, errDoubleLock): - zlog.Debug(parent). - Err(err). - Str("key", key). - Msg("lock failed") + slog.DebugContext(parent, "lock failed", a, "reason", err) default: - zlog.Info(parent). - Err(err). - Msg("checking lock liveness") + slog.InfoContext(parent, "checking lock liveness", a, "reason", err) l.rc.Broadcast() } @@ -343,18 +316,14 @@ func (l *Locker) unlock(ctx context.Context, key string, kb []byte, gen int, nex [][]byte{kb}, nil, []int16{1}, nil).Close() if err != nil { - zlog.Debug(ctx). - Err(err). - Msg("error during unlock") + slog.DebugContext(ctx, "error during unlock", "reason", err) // Since we're in a different call path now, we need to signal on // error here, as well. l.rc.Broadcast() return } if _, ok := l.cur[key]; !ok || tag.RowsAffected() == 0 { - zlog.Error(ctx). - Str("key", key). - Msg("lock protocol botch") + slog.ErrorContext(ctx, "lock protocol botch", "key", key) } delete(l.cur, key) } diff --git a/pkg/ctxlock/v2/ctxlock_test.go b/pkg/ctxlock/v2/ctxlock_test.go index 32ce37c03..6e1e4d8c8 100644 --- a/pkg/ctxlock/v2/ctxlock_test.go +++ b/pkg/ctxlock/v2/ctxlock_test.go @@ -1,12 +1,10 @@ package ctxlock import ( - "strconv" "sync" "testing" "github.com/google/uuid" - "github.com/quay/zlog" ) func TestUncontested(t *testing.T) { @@ -32,7 +30,6 @@ func TestUncontested(t *testing.T) { for i := range wi { go func(i int) { defer wg.Done() - ctx := zlog.ContextWithValues(ctx, "worker", strconv.Itoa(i)) <-start t.Logf("worker %d: start", i) for _, id := range wi[i] { @@ -68,7 +65,6 @@ func TestContested(t *testing.T) { for i := range w { go func(i int) { defer wg.Done() - ctx := zlog.ContextWithValues(ctx, "worker", strconv.Itoa(i)) <-start t.Logf("worker %d: start", i) for _, id := range ids { diff --git a/pkg/ctxlock/v2/main_test.go b/pkg/ctxlock/v2/main_test.go index a8f476deb..f0e846306 100644 --- a/pkg/ctxlock/v2/main_test.go +++ b/pkg/ctxlock/v2/main_test.go @@ -7,15 +7,15 @@ import ( "github.com/jackc/pgx/v5/log/testingadapter" "github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/tracelog" - "github.com/quay/zlog" + "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" ) func basicSetup(t testing.TB) (context.Context, *Locker) { t.Helper() integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) // Setup the Database. db, err := integration.NewDB(ctx, t) diff --git a/pkg/ovalutil/dpkg.go b/pkg/ovalutil/dpkg.go index 8475d34ec..1434066de 100644 --- a/pkg/ovalutil/dpkg.go +++ b/pkg/ovalutil/dpkg.go @@ -4,12 +4,11 @@ import ( "context" "errors" "fmt" + "log/slog" "regexp" "strings" "github.com/quay/goval-parser/oval" - "github.com/quay/zlog" - "github.com/rs/zerolog" "github.com/quay/claircore" ) @@ -23,7 +22,6 @@ type PackageExpansionFunc func(def oval.Definition, name *oval.DpkgName) []strin // // Each Criterion encountered with an EVR string will be translated into a claircore.Vulnerability func DpkgDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulnsFunc, expansionFunc PackageExpansionFunc) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "ovalutil/DpkgDefsToVulns") vulns := make([]*claircore.Vulnerability, 0, 10000) pkgcache := map[string]*claircore.Package{} cris := []*oval.Criterion{} @@ -36,10 +34,7 @@ func DpkgDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulns // create our prototype vulnerability protoVulns, err := protoVulns(def) if err != nil { - zlog.Debug(ctx). - Err(err). - Str("def_id", def.ID). - Msg("could not create prototype vulnerabilities") + slog.DebugContext(ctx, "could not create prototype vulnerabilities", "reason", err, "def_id", def.ID) continue } // recursively collect criterions for this definition @@ -131,19 +126,16 @@ func DpkgDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulns } } } - zlog.Debug(ctx). - Int("test", stats.Test). - Int("object", stats.Obj). - Int("state", stats.State). - Msg("ref lookup failures") - if ev := zlog.Debug(ctx); ev.Enabled() { - d := zerolog.Dict() + slog.DebugContext(ctx, "ref lookup failures", + "test", stats.Test, + "object", stats.Obj, + "state", stats.State) + if slog.Default().Enabled(ctx, slog.LevelDebug) { + var bad []slog.Attr for k, v := range badvers { - d.Str(k, v) + bad = append(bad, slog.String(k, v)) } - ev. - Dict("package-version", d). - Msg("bogus versions") + slog.DebugContext(ctx, "bogus versions", "package-version", slog.GroupValue(bad...)) } return vulns, nil } diff --git a/pkg/ovalutil/fetcher.go b/pkg/ovalutil/fetcher.go index d0a0af646..49cdf95d6 100644 --- a/pkg/ovalutil/fetcher.go +++ b/pkg/ovalutil/fetcher.go @@ -6,13 +6,12 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "mime" "net/http" "net/url" "path" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" "github.com/quay/claircore/pkg/tmp" ) @@ -66,7 +65,6 @@ type Fetcher struct { // For users that embed a Fetcher, this provides a configuration hook by // default. func (f *Fetcher) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, "component", "pkg/ovalutil/Fetcher.Configure") var cfg FetcherConfig if err := cf(&cfg); err != nil { return err @@ -77,8 +75,7 @@ func (f *Fetcher) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c return err } f.URL = uri - zlog.Info(ctx). - Msg("configured database URL") + slog.InfoContext(ctx, "configured database URL") } if cfg.Compression != "" { c, err := ParseCompressor(cfg.Compression) @@ -86,8 +83,7 @@ func (f *Fetcher) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c return err } f.Compression = c - zlog.Info(ctx). - Msg("configured database compression") + slog.InfoContext(ctx, "configured database compression") } f.Client = c @@ -112,8 +108,7 @@ type FetcherConfig struct { // // Tmp.File is used to return a ReadCloser that outlives the passed-in context. func (f *Fetcher) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "pkg/ovalutil/Fetcher.Fetch") - zlog.Info(ctx).Str("database", f.URL.String()).Msg("starting fetch") + slog.InfoContext(ctx, "starting fetch", "database", f.URL) req := http.Request{ Method: http.MethodGet, Header: http.Header{ @@ -150,7 +145,7 @@ func (f *Fetcher) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCl default: return nil, hint, fmt.Errorf("ovalutil: fetcher got unexpected HTTP response: %d (%s)", res.StatusCode, res.Status) } - zlog.Debug(ctx).Msg("request ok") + slog.DebugContext(ctx, "request ok") var r io.Reader cmp := f.Compression @@ -186,11 +181,10 @@ Compression: default: panic("unreachable") } - zlog.Debug(ctx). - Err(err). - Str("header", h). - Str("value", v). - Msg("failed to parse incoming HTTP header") + slog.DebugContext(ctx, "failed to parse incoming HTTP header", + "reason", err, + "header", h, + "value", v) } kind = mime.TypeByExtension(path.Ext(res.Request.URL.Path)) Found: @@ -227,23 +221,19 @@ Compression: default: panic(fmt.Sprintf("ovalutil: programmer error: unknown compression scheme: %v", f.Compression)) } - zlog.Debug(ctx). - Stringer("compression", cmp). - Msg("found compression scheme") + slog.DebugContext(ctx, "found compression scheme", "compression", cmp) tf, err := tmp.NewFile("", "fetcher.") if err != nil { return nil, hint, err } - zlog.Debug(ctx). - Str("path", tf.Name()). - Msg("using tempfile") + slog.DebugContext(ctx, "using tempfile", "path", tf.Name()) success := false defer func() { if !success { - zlog.Debug(ctx).Msg("unsuccessful, cleaning up tempfile") + slog.DebugContext(ctx, "unsuccessful, cleaning up tempfile") if err := tf.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("failed to close tempfile") + slog.WarnContext(ctx, "failed to close tempfile", "reason", err) } } }() @@ -254,7 +244,7 @@ Compression: if o, err := tf.Seek(0, io.SeekStart); err != nil || o != 0 { return nil, hint, err } - zlog.Debug(ctx).Msg("decompressed and buffered database") + slog.DebugContext(ctx, "decompressed and buffered database") fp.From(res.Header) hint = fp.Fingerprint() diff --git a/pkg/ovalutil/rpm.go b/pkg/ovalutil/rpm.go index f3cd9430b..ce6cc27f2 100644 --- a/pkg/ovalutil/rpm.go +++ b/pkg/ovalutil/rpm.go @@ -4,10 +4,10 @@ import ( "context" "errors" "fmt" + "log/slog" "regexp" "github.com/quay/goval-parser/oval" - "github.com/quay/zlog" "github.com/quay/claircore" ) @@ -41,17 +41,15 @@ type ProtoVulnsFunc func(def oval.Definition) ([]*claircore.Vulnerability, error // // Each Criterion encountered with an EVR string will be translated into a claircore.Vulnerability func RPMDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulnsFunc) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "ovalutil/RPMDefsToVulns") vulns := make([]*claircore.Vulnerability, 0, 10000) cris := []*oval.Criterion{} for _, def := range root.Definitions.Definitions { // create our prototype vulnerability protoVulns, err := protoVulns(def) if err != nil { - zlog.Debug(ctx). - Err(err). - Str("def_id", def.ID). - Msg("could not create prototype vulnerabilities") + slog.DebugContext(ctx, "could not create prototype vulnerabilities", + "reason", err, + "def_id", def.ID) continue } // recursively collect criterions for this definition @@ -77,7 +75,7 @@ func RPMDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulnsF case errors.Is(err, errTestSkip): continue default: - zlog.Debug(ctx).Str("test_ref", criterion.TestRef).Msg("test ref lookup failure. moving to next criterion") + slog.DebugContext(ctx, "test ref lookup failure, moving to next criterion", "test_ref", criterion.TestRef) continue } @@ -98,10 +96,9 @@ func RPMDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulnsF // We only handle rpminfo_objects. continue default: - zlog.Debug(ctx). - Err(err). - Str("object_ref", objRef). - Msg("failed object lookup. moving to next criterion") + slog.DebugContext(ctx, "failed object lookup, moving to next criterion", + "reason", err, + "object_ref", objRef) continue } @@ -113,10 +110,9 @@ func RPMDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulnsF stateRef := stateRefs[0].StateRef state, err = rpmStateLookup(root, stateRef) if err != nil { - zlog.Debug(ctx). - Err(err). - Str("state_ref", stateRef). - Msg("failed state lookup. moving to next criterion") + slog.DebugContext(ctx, "failed state lookup, moving to next criterion", + "reason", err, + "state_ref", stateRef) continue } // if we find a state, but this state does not contain an EVR, diff --git a/python/matcher.go b/python/matcher.go index 737c5004f..dec42af2f 100644 --- a/python/matcher.go +++ b/python/matcher.go @@ -2,10 +2,9 @@ package python import ( "context" + "log/slog" "net/url" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" "github.com/quay/claircore/pkg/pep440" @@ -42,10 +41,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v // Parse the package first. If it cannot be parsed, it cannot properly be analyzed for vulnerabilities. rv, err := pep440.Parse(record.Package.Version) if err != nil { - zlog.Warn(ctx). - Str("package", record.Package.Name). - Stringer("version", &rv). - Msg("unable to parse python package version") + slog.WarnContext(ctx, "unable to parse python package version", + "package", record.Package.Name, + "version", &rv) return false, err } @@ -59,10 +57,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v if introduced != "" { iv, err := pep440.Parse(introduced) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", introduced). - Msg("unable to parse python introduced version") + slog.WarnContext(ctx, "unable to parse python introduced version", + "package", vuln.Package.Name, + "version", introduced) return false, err } // If the package's version is less than the introduced version, it's not vulnerable. @@ -77,10 +74,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v case fixedVersion != "": uv, err := pep440.Parse(fixedVersion) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", fixedVersion). - Msg("unable to parse python fixed version") + slog.WarnContext(ctx, "unable to parse python fixed version", + "package", vuln.Package.Name, + "version", fixedVersion) return false, err } // The package is affected if its version is less than the fixed version. @@ -88,10 +84,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v case lastAffected != "": la, err := pep440.Parse(lastAffected) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", lastAffected). - Msg("unable to parse python last_affected version") + slog.WarnContext(ctx, "unable to parse python last_affected version", + "package", vuln.Package.Name, + "version", lastAffected) return false, err } // The package is affected if its version is less than or equal to the last affected version. diff --git a/python/matcher_test.go b/python/matcher_test.go index 6b9ee5101..186d50286 100644 --- a/python/matcher_test.go +++ b/python/matcher_test.go @@ -1,11 +1,9 @@ package python_test import ( - "context" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" @@ -23,7 +21,7 @@ type matcherTestcase struct { func (tc matcherTestcase) Run(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) got, err := tc.Matcher.Vulnerable(ctx, &tc.R, &tc.V) if err != nil { t.Error(err) @@ -238,7 +236,8 @@ func TestMatcher(t *testing.T) { for _, testcase := range testcases { t.Run(testcase.Name, func(t *testing.T) { - got, err := testcase.Matcher.Vulnerable(context.Background(), &testcase.R, &testcase.V) + ctx := test.Logging(t) + got, err := testcase.Matcher.Vulnerable(ctx, &testcase.R, &testcase.V) if err != nil { t.Fatal(err) } @@ -248,5 +247,6 @@ func TestMatcher(t *testing.T) { }) } - test.RunMatcherTests(zlog.Test(context.Background(), t), t, "testdata/matcher", new(python.Matcher)) + ctx := test.Logging(t) + test.RunMatcherTests(ctx, t, "testdata/matcher", new(python.Matcher)) } diff --git a/python/packagescanner.go b/python/packagescanner.go index 6f6eb8d96..df990411a 100644 --- a/python/packagescanner.go +++ b/python/packagescanner.go @@ -8,14 +8,13 @@ import ( "context" "fmt" "io/fs" + "log/slog" "net/textproto" "path" "path/filepath" "runtime/trace" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/pkg/pep440" @@ -59,12 +58,8 @@ func (*Scanner) Kind() string { return "package" } func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore.Package, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "python/Scanner.Scan", - "version", ps.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") if err := ctx.Err(); err != nil { return nil, err } @@ -85,9 +80,7 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco } for _, n := range ms { if set.Contains(n) { - zlog.Debug(ctx). - Str("path", n). - Msg("file path determined to be of RPM origin") + slog.DebugContext(ctx, "file path determined to be of RPM origin", "path", n) continue } b, err := fs.ReadFile(sys, n) @@ -99,18 +92,12 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco rd := textproto.NewReader(bufio.NewReader(bytes.NewReader(b))) hdr, err := rd.ReadMIMEHeader() if err != nil && hdr == nil { - zlog.Warn(ctx). - Err(err). - Str("path", n). - Msg("unable to read metadata, skipping") + slog.WarnContext(ctx, "unable to read metadata, skipping", "reason", err, "path", n) continue } v, err := pep440.Parse(hdr.Get("Version")) if err != nil { - zlog.Warn(ctx). - Err(err). - Str("path", n). - Msg("couldn't parse the version, skipping") + slog.WarnContext(ctx, "couldn't parse the version, skipping", "reason", err, "path", n) continue } pkgDB := filepath.Join(n, "..", "..") @@ -172,14 +159,7 @@ func findDeliciousEgg(ctx context.Context, sys fs.FS) (out []string, err error) } return out, fs.WalkDir(sys, ".", func(p string, d fs.DirEntry, err error) error { - ev := zlog.Debug(ctx). - Str("file", p) - var success bool - defer func() { - if !success { - ev.Discard().Send() - } - }() + attrs := []slog.Attr{slog.String("file", p)} switch { case err != nil: return err @@ -190,15 +170,15 @@ func findDeliciousEgg(ctx context.Context, sys fs.FS) (out []string, err error) switch { case isRPM: pat = `usr/lib*/python[23].*` - ev = ev.Bool("rpm_dir", true) + attrs = append(attrs, slog.Bool("rpm_dir", true)) case dpkg: pat = `usr/lib*/python[23]` - ev = ev.Bool("dpkg_dir", true) + attrs = append(attrs, slog.Bool("dpkg_dir", true)) default: panic("programmer error: unreachable") } if m, _ := path.Match(pat, p); m { - ev.Msg("skipping directory") + slog.LogAttrs(ctx, slog.LevelDebug, "skipping directory", attrs...) return fs.SkipDir } fallthrough @@ -208,29 +188,28 @@ func findDeliciousEgg(ctx context.Context, sys fs.FS) (out []string, err error) case strings.HasPrefix(filepath.Base(p), ".wh."): return nil case strings.HasSuffix(p, `.egg/EGG-INFO/PKG-INFO`): - ev = ev.Str("kind", ".egg") + attrs = append(attrs, slog.String("kind", ".egg")) case strings.HasSuffix(p, `.egg-info`): fallthrough case strings.HasSuffix(p, `.egg-info/PKG-INFO`): - ev = ev.Str("kind", ".egg-info") + attrs = append(attrs, slog.String("kind", ".egg-info")) case strings.HasSuffix(p, `.dist-info/METADATA`): - ev = ev.Str("kind", "wheel") + attrs = append(attrs, slog.String("kind", "wheel")) // See if we can discern the installer. var installer string ip := path.Join(path.Dir(p), `INSTALLER`) if ic, err := fs.ReadFile(sys, ip); err == nil { installer = string(bytes.TrimSpace(ic)) - ev = ev.Str("installer", installer) + attrs = append(attrs, slog.String("installer", installer)) } if _, ok := blocklist[installer]; ok { - ev.Msg("skipping package") + slog.LogAttrs(ctx, slog.LevelDebug, "skipping package", attrs...) return nil } default: return nil } - ev.Msg("found package") - success = true + slog.LogAttrs(ctx, slog.LevelDebug, "found package", attrs...) out = append(out, p) return nil }) diff --git a/python/packagescanner_test.go b/python/packagescanner_test.go index fe6d502b8..9306cf4b5 100644 --- a/python/packagescanner_test.go +++ b/python/packagescanner_test.go @@ -13,7 +13,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/python" @@ -80,7 +79,6 @@ var scanTable = []test.ScannerTestcase{ func TestScanLocal(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) type testcase struct { Name string @@ -97,7 +95,7 @@ func TestScanLocal(t *testing.T) { for _, tt := range table { t.Run(tt.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f, err := os.Open(tt.Path) if err != nil { t.Fatal(err) diff --git a/rhel/coalescer.go b/rhel/coalescer.go index 0d017354a..faa99b323 100644 --- a/rhel/coalescer.go +++ b/rhel/coalescer.go @@ -2,11 +2,11 @@ package rhel import ( "context" + "log/slog" "net/url" "github.com/quay/claircore" "github.com/quay/claircore/indexer" - "github.com/quay/zlog" ) // Coalescer takes individual layer artifacts and coalesces them into a full @@ -128,10 +128,7 @@ func (*Coalescer) Coalesce(ctx context.Context, artifacts []*indexer.LayerArtifa for _, repo := range layerArtifacts.Repos { uri, err := url.ParseQuery(repo.URI) if err != nil { - zlog.Warn(ctx). - Err(err). - Str("repository", repo.URI). - Msg("unable to parse repository URI") + slog.WarnContext(ctx, "unable to parse repository URI", "repository", repo.URI) continue } repoRepoid := uri.Get("repoid") diff --git a/rhel/coalescer_test.go b/rhel/coalescer_test.go index 9aec1eb61..395f6b806 100644 --- a/rhel/coalescer_test.go +++ b/rhel/coalescer_test.go @@ -9,7 +9,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/quay/claircore/toolkit/types/cpe" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -23,7 +22,7 @@ type CoalescerTestcase struct { func (tc CoalescerTestcase) Run(ctx context.Context, t *testing.T) { t.Run(tc.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t, ctx) input, want := tc.Fixture(t) got, err := new(Coalescer).Coalesce(ctx, input) if err != nil { @@ -38,7 +37,7 @@ func (tc CoalescerTestcase) Run(ctx context.Context, t *testing.T) { func TestCoalescer(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) tcs := []CoalescerTestcase{ { diff --git a/rhel/distributionscanner.go b/rhel/distributionscanner.go index c68516a66..588783d75 100644 --- a/rhel/distributionscanner.go +++ b/rhel/distributionscanner.go @@ -5,12 +5,11 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "regexp" "runtime/trace" "strconv" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -40,12 +39,8 @@ func (*DistributionScanner) Kind() string { return "distribution" } // Scan implements [indexer.DistributionScanner]. func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "rhel/DistributionScanner.Scan", - "version", ds.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { return nil, fmt.Errorf("rhel: unable to open layer: %w", err) @@ -55,7 +50,7 @@ func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([] return nil, fmt.Errorf("rhel: unexpected error reading files: %w", err) } if d == nil { - zlog.Debug(ctx).Msg("didn't find an os-release or redhat-release file") + slog.DebugContext(ctx, "didn't find an os-release or redhat-release file") return nil, nil } return []*claircore.Distribution{d}, nil diff --git a/rhel/internal/common/updater.go b/rhel/internal/common/updater.go index 41c0fad5b..6fb9828a7 100644 --- a/rhel/internal/common/updater.go +++ b/rhel/internal/common/updater.go @@ -4,13 +4,13 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "net/http" "reflect" "sync" "sync/atomic" "time" - "github.com/quay/zlog" "golang.org/x/time/rate" ) @@ -44,16 +44,12 @@ func NewUpdater(url string, init any) *Updater { // Get returns a pointer to the current copy of the value. The Get call may be // hijacked to update the value from the configured endpoint. func (u *Updater) Get(ctx context.Context, c *http.Client) (any, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "rhel/internal/common/Updater.Get") var err error if u.url != "" && u.reqRate.Allow() { - zlog.Debug(ctx).Msg("got unlucky, updating mapping file") + slog.DebugContext(ctx, "got unlucky, updating mapping file") err = u.Fetch(ctx, c) if err != nil { - zlog.Error(ctx). - Err(err). - Msg("error updating mapping file") + slog.ErrorContext(ctx, "error updating mapping file", "reason", err) } } @@ -64,10 +60,8 @@ func (u *Updater) Get(ctx context.Context, c *http.Client) (any, error) { // // Fetch is safe to call concurrently. func (u *Updater) Fetch(ctx context.Context, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, - "component", "rhel/internal/common/Updater.Fetch", - "url", u.url) - zlog.Debug(ctx).Msg("attempting fetch of mapping file") + log := slog.With("url", u.url) + log.DebugContext(ctx, "attempting fetch of mapping file") req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.url, nil) if err != nil { @@ -87,9 +81,7 @@ func (u *Updater) Fetch(ctx context.Context, c *http.Client) error { switch resp.StatusCode { case http.StatusOK: case http.StatusNotModified: - zlog.Debug(ctx). - Str("since", u.lastModified). - Msg("response not modified; no update necessary") + log.DebugContext(ctx, "response not modified; no update necessary", "since", u.lastModified) return nil default: return fmt.Errorf("received status code %d querying mapping url", resp.StatusCode) @@ -105,6 +97,6 @@ func (u *Updater) Fetch(ctx context.Context, c *http.Client) error { u.mu.Unlock() // atomic store of mapping file u.value.Store(v) - zlog.Debug(ctx).Msg("atomic update of local mapping file complete") + log.DebugContext(ctx, "atomic update of local mapping file complete") return nil } diff --git a/rhel/matcher.go b/rhel/matcher.go index d197973dd..e5dfd3687 100644 --- a/rhel/matcher.go +++ b/rhel/matcher.go @@ -2,10 +2,10 @@ package rhel import ( "context" + "log/slog" "strings" version "github.com/knqyf263/go-rpm-version" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" @@ -72,10 +72,7 @@ func (m *Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, // support the claircore.Vulnerability.Repo.CPE field. vuln.Repo.CPE, err = cpe.Unbind(vuln.Repo.Name) if err != nil { - zlog.Warn(ctx). - Str("vulnerability name", vuln.Name). - Err(err). - Msg("unable to unbind repo CPE") + slog.WarnContext(ctx, "unable to unbind repo CPE", "reason", err, "vulnerability name", vuln.Name) return false, nil } if !cpe.Compare(vuln.Repo.CPE, record.Repository.CPE).IsSuperset() && !IsCPESubstringMatch(record.Repository.CPE, vuln.Repo.CPE) { diff --git a/rhel/matcher_test.go b/rhel/matcher_test.go index 8caa589ef..9b701afbe 100644 --- a/rhel/matcher_test.go +++ b/rhel/matcher_test.go @@ -1,12 +1,10 @@ package rhel import ( - "context" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" + "github.com/quay/claircore/test" "github.com/quay/claircore/toolkit/types/cpe" ) @@ -155,8 +153,7 @@ func TestVulnerable(t *testing.T) { } m := &Matcher{} - ctx := context.Background() - ctx = zlog.Test(ctx, t) + ctx := test.Logging(t) for _, tc := range testCases { got, err := m.Vulnerable(ctx, tc.ir, tc.v) if err != nil { diff --git a/rhel/matcherfactory.go b/rhel/matcherfactory.go index 135eded2c..d16a9d390 100644 --- a/rhel/matcherfactory.go +++ b/rhel/matcherfactory.go @@ -2,10 +2,9 @@ package rhel import ( "context" + "log/slog" "net/http" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" ) @@ -18,7 +17,7 @@ type MatcherFactory struct { ignoreUnpatched bool } -// MatcherFactory implements [driver.MatcherFactory] +// Matcher implements [driver.MatcherFactory] func (f *MatcherFactory) Matcher(ctx context.Context) ([]driver.Matcher, error) { m := &Matcher{ ignoreUnpatched: f.ignoreUnpatched, @@ -30,16 +29,13 @@ type MatcherFactoryConfig struct { IgnoreUnpatched bool `json:"ignore_unpatched" yaml:"ignore_unpatched"` } -// MatcherFactory implements driver.MatcherConfigurable. +// Configure implements [driver.MatcherConfigurable]. func (f *MatcherFactory) Configure(ctx context.Context, cfg driver.MatcherConfigUnmarshaler, _ *http.Client) error { var fc MatcherFactoryConfig if err := cfg(&fc); err != nil { return err } f.ignoreUnpatched = fc.IgnoreUnpatched - zlog.Info(ctx). - Str("component", "rhel/MatcherFactory.Configure"). - Bool("ignore_unpatched", f.ignoreUnpatched). - Msg("configured") + slog.InfoContext(ctx, "configured", "ignore_unpatched", f.ignoreUnpatched) return nil } diff --git a/rhel/packagescanner.go b/rhel/packagescanner.go index 8ccf02a94..5285803cf 100644 --- a/rhel/packagescanner.go +++ b/rhel/packagescanner.go @@ -5,14 +5,14 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/internal/dnf" "github.com/quay/claircore/internal/rpm" + "github.com/quay/claircore/toolkit/log" ) var _ indexer.PackageScanner = PackageScanner{} @@ -40,12 +40,8 @@ func (p PackageScanner) Scan(ctx context.Context, layer *claircore.Layer) (out [ } defer trace.StartRegion(ctx, "PackageScanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "rhel/PackageScanner.Scan", - "version", p.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := layer.FS() if err != nil { @@ -65,8 +61,8 @@ func (p PackageScanner) Scan(ctx context.Context, layer *claircore.Layer) (out [ }() for found := range found { err = func() error { - ctx := zlog.ContextWithValues(ctx, "db", found.String()) - zlog.Debug(ctx).Msg("examining database") + ctx := log.With(ctx, "db", found) + slog.DebugContext(ctx, "examining database") db, err := rpm.OpenDB(ctx, sys, found) switch { case err == nil: diff --git a/rhel/packagescanner_test.go b/rhel/packagescanner_test.go index ea8506476..99141ac02 100644 --- a/rhel/packagescanner_test.go +++ b/rhel/packagescanner_test.go @@ -1,7 +1,6 @@ package rhel import ( - "context" "errors" "io/fs" "net/url" @@ -10,7 +9,6 @@ import ( "testing" "github.com/quay/claircore" - "github.com/quay/zlog" "github.com/quay/claircore/test" "github.com/quay/claircore/test/rpmtest" @@ -23,7 +21,7 @@ import ( func TestPackageDetection(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) ms, err := filepath.Glob("testdata/package/*.txtar") if err != nil { panic("programmer error") // static glob @@ -57,7 +55,6 @@ func TestPackageDetection(t *testing.T) { // get repoid information. func TestPackageScannerDNFWrapLogic(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) tests := []struct { name string @@ -88,7 +85,7 @@ func TestPackageScannerDNFWrapLogic(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) // Create layer from tar file f, err := os.Open(tt.layerPath) @@ -145,7 +142,6 @@ func TestPackageScannerDNFWrapLogic(t *testing.T) { if !tt.expectRepoidHint && packagesWithRepoid > 0 { t.Errorf("Expected no packages to have repoid hints, but found %d", packagesWithRepoid) - } }) } @@ -155,7 +151,7 @@ func TestPackageScannerDNFWrapLogic(t *testing.T) { // are surfaced to the caller instead of being swallowed. func TestPackageScannerPropagatesFindDBErrors(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) // Point the layer at a non-existent directory to force WalkDir to fail immediately. missingRoot := filepath.Join(t.TempDir(), "missing-root") diff --git a/rhel/repositoryscanner.go b/rhel/repositoryscanner.go index a55bbefd2..b4e463c8d 100644 --- a/rhel/repositoryscanner.go +++ b/rhel/repositoryscanner.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "net/http" "net/url" "os" @@ -16,8 +17,6 @@ import ( "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/internal/dnf" @@ -108,9 +107,6 @@ func (*RepositoryScanner) Kind() string { return "repository" } // Configure implements [indexer.RPCScanner]. func (r *RepositoryScanner) Configure(ctx context.Context, f indexer.ConfigDeserializer, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, - "component", "rhel/RepositoryScanner.Configure", - "version", r.Version()) r.client = c if err := f(&r.cfg); err != nil { return err @@ -157,12 +153,8 @@ func (r *RepositoryScanner) Configure(ctx context.Context, f indexer.ConfigDeser // stored in the [claircore.Repository]'s "Name" and "CPE" fields, respectively. func (r *RepositoryScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Repository, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "rhel/RepositoryScanner.Scan", - "version", r.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { @@ -220,11 +212,10 @@ func (r *RepositoryScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*cl for repoid, cpeID := range pairs { c, err := cpe.Unbind(cpeID) if err != nil { - zlog.Warn(ctx). - Err(err). - Str("url", bugURL(cpeID, err)). - Str("cpeID", cpeID). - Msg("invalid CPE, please report a bug upstream") + slog.WarnContext(ctx, "invalid CPE, please report a bug upstream", + "reason", err, + "cpeID", cpeID, + "url", bugURL(cpeID, err)) continue } @@ -257,7 +248,7 @@ func (r *RepositoryScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*cl } // BugURL constructs a link directly to the Red Hat Jira instance. -func bugURL(id string, err error) string { +func bugURL(id string, err error) *url.URL { const desc = "A Clair instance noticed an invalid CPE:{code}%s{code}\nThe reported error was:{code}%v{code}" v := url.Values{ "pid": {"12330022"}, // ID for the Red Hat Jira "SECDATA" project. @@ -271,7 +262,7 @@ func bugURL(id string, err error) string { Path: "/secure/CreateIssueDetails!init.jspa", RawQuery: v.Encode(), } - return u.String() + return &u } // RepoidsFromContentSets returns a slice of repoids, as discovered by examining @@ -304,9 +295,7 @@ func (m *mappingFile) GetOne(ctx context.Context, repoid string) (cpes []string, if repo, ok := m.Data[repoid]; ok { return repo.CPEs, true } - zlog.Debug(ctx). - Str("repository", repoid). - Msg("repository not present in a mapping file") + slog.DebugContext(ctx, "repository not present in a mapping file", "repository", repoid) return nil, false } diff --git a/rhel/repositoryscanner_test.go b/rhel/repositoryscanner_test.go index 9692172c8..ce390145a 100644 --- a/rhel/repositoryscanner_test.go +++ b/rhel/repositoryscanner_test.go @@ -2,7 +2,6 @@ package rhel import ( "bytes" - "context" "encoding/json" "errors" "io" @@ -16,7 +15,6 @@ import ( "github.com/quay/claircore/pkg/tmp" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" @@ -25,7 +23,6 @@ import ( func TestRepositoryScanner(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) repoData := ` { @@ -320,7 +317,7 @@ func TestRepositoryScanner(t *testing.T) { for _, tt := range table { t.Run(tt.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f, err := os.Open(tt.layerPath) if err != nil { t.Fatal(err) @@ -388,7 +385,7 @@ func TestBugURL(t *testing.T) { if err == nil { t.Error("expected error") } - got := bugURL(in, err) + got := bugURL(in, err).String() t.Logf("\ngot: %s\nwant: %s", got, want) if got != want { diff --git a/rhel/rhcc/coalescer_test.go b/rhel/rhcc/coalescer_test.go index fa5a281fc..edd571d46 100644 --- a/rhel/rhcc/coalescer_test.go +++ b/rhel/rhcc/coalescer_test.go @@ -1,12 +1,9 @@ package rhcc import ( - "context" "encoding/json" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/test" @@ -14,7 +11,7 @@ import ( func TestCoalescer(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) coalescer := &coalescer{} repo := []*claircore.Repository{&GoldRepo} repo[0].ID = "1" // Assign it an ID and check it later. diff --git a/rhel/rhcc/detector.go b/rhel/rhcc/detector.go index 675e54e3f..c82868379 100644 --- a/rhel/rhcc/detector.go +++ b/rhel/rhcc/detector.go @@ -6,11 +6,10 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "strconv" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/pkg/rhctag" @@ -43,7 +42,6 @@ func (s *detector) Kind() string { return "package" } // It performs a package scan on the given layer and returns all the RHEL // container identifying metadata by using the labels.json file. func (s *detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Package, error) { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/rhcc/detector.Scan") if err := ctx.Err(); err != nil { return nil, err } @@ -62,7 +60,7 @@ func (s *detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.P // Check if required fields are present if labels.Name == "" || labels.Architecture == "" || labels.Created.IsZero() { - zlog.Warn(ctx).Msg("required labels not found in labels.json") + slog.WarnContext(ctx, "required labels not found in labels.json") return nil, nil } @@ -70,7 +68,7 @@ func (s *detector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.P rhctagVersion, err := rhctag.Parse(vr) if err != nil { // A unix timestamp should always parse, so this is unexpected. - zlog.Warn(ctx).Err(err).Str("version", vr).Msg("failed to parse rhctag version") + slog.WarnContext(ctx, "failed to parse rhctag version", "reason", err, "version", vr) return nil, nil } @@ -146,7 +144,6 @@ func (s *repoDetector) Kind() string { return "repository" } // It performs a repository scan on the given layer and returns all the RHEL // container identifying metadata by using the labels.json file. func (s *repoDetector) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Repository, error) { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/rhcc/repoDetector.Scan") if err := ctx.Err(); err != nil { return nil, err } @@ -176,5 +173,4 @@ func (s *repoDetector) Scan(ctx context.Context, l *claircore.Layer) ([]*clairco Key: RepositoryKey, }, }, nil - } diff --git a/rhel/rhcc/detector_test.go b/rhel/rhcc/detector_test.go index 1c197e352..c2010c628 100644 --- a/rhel/rhcc/detector_test.go +++ b/rhel/rhcc/detector_test.go @@ -2,14 +2,12 @@ package rhcc import ( "archive/tar" - "context" "io" "os" "strings" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" @@ -18,7 +16,7 @@ import ( func TestPackageDetector(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) type testcase struct { Name string @@ -130,7 +128,7 @@ func TestPackageDetector(t *testing.T) { }) for _, tt := range table { t.Run(tt.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) mod := test.Modtime(t, tt.LabelsFile) a.GenerateLayer(t, tt.Name, mod, genLayerFunc(tt.LabelsFile, tt.LabelsPath)) @@ -164,7 +162,7 @@ func TestPackageDetector(t *testing.T) { func TestRepositoryDetector(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) type testcase struct { Name string @@ -218,7 +216,7 @@ func TestRepositoryDetector(t *testing.T) { }) for _, tt := range table { t.Run(tt.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) mod := test.Modtime(t, tt.LabelsFile) a.GenerateLayer(t, tt.Name, mod, genLayerFunc(tt.LabelsFile, tt.LabelsPath)) diff --git a/rhel/rhcc/matcher.go b/rhel/rhcc/matcher.go index fcc7c52d5..1b156b61b 100644 --- a/rhel/rhcc/matcher.go +++ b/rhel/rhcc/matcher.go @@ -2,9 +2,9 @@ package rhcc import ( "context" + "log/slog" rpmVersion "github.com/knqyf263/go-rpm-version" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" @@ -43,10 +43,7 @@ func (*matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v // This is not a gold repo record, so we need to check if the CPE matches. vuln.Repo.CPE, err = cpe.Unbind(vuln.Repo.Name) if err != nil { - zlog.Warn(ctx). - Str("vulnerability name", vuln.Name). - Err(err). - Msg("unable to unbind repo CPE") + slog.WarnContext(ctx, "unable to unbind repo CPE", "reason", err, "vulnerability name", vuln.Name) return false, nil } if !cpe.Compare(vuln.Repo.CPE, record.Repository.CPE).IsSuperset() && !rhel.IsCPESubstringMatch(record.Repository.CPE, vuln.Repo.CPE) { @@ -54,10 +51,7 @@ func (*matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v } } pkgVer, fixedInVer := rpmVersion.NewVersion(record.Package.Version), rpmVersion.NewVersion(vuln.FixedInVersion) - zlog.Debug(ctx). - Str("record", record.Package.Version). - Str("vulnerability", vuln.FixedInVersion). - Msg("comparing versions") + slog.DebugContext(ctx, "comparing versions", "record", record.Package.Version, "vulnerability", vuln.FixedInVersion) return pkgVer.LessThan(fixedInVer), nil } diff --git a/rhel/rhcc/scanner.go b/rhel/rhcc/scanner.go index 39e2f27de..bb5a9b105 100644 --- a/rhel/rhcc/scanner.go +++ b/rhel/rhcc/scanner.go @@ -6,13 +6,12 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "net/http" "os" "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/internal/zreader" @@ -62,7 +61,6 @@ const DefaultName2ReposMappingURL = "https://security.access.redhat.com/data/met // Configure implements [indexer.RPCScanner]. func (s *scanner) Configure(ctx context.Context, f indexer.ConfigDeserializer, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/rhcc/scanner.Configure") s.client = c if err := f(&s.cfg); err != nil { return err @@ -117,7 +115,6 @@ func (s *scanner) Kind() string { return "package" } // Scan implements [indexer.PackageScanner]. func (s *scanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Package, error) { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/rhcc/scanner.Scan") const ( compLabel = `com.redhat.component` nameLabel = `name` @@ -160,7 +157,7 @@ func (s *scanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pa var ok bool (*chk.Found), ok = labels[chk.Want] if !ok { - zlog.Info(ctx).Str("label", chk.Want).Msg("expected label not found in dockerfile") + slog.InfoContext(ctx, "expected label not found in dockerfile", "label", chk.Want) return nil, nil } } @@ -189,8 +186,7 @@ func (s *scanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Pa } repos, ok := v.Data[name] if ok { - zlog.Debug(ctx).Str("name", name). - Msg("name present in mapping file") + slog.DebugContext(ctx, "name present in mapping file", "name", name) } else { // Didn't find external_repos in mapping, use name label as package // name. @@ -229,9 +225,7 @@ func findLabels(ctx context.Context, sys fs.FS) (map[string]string, string, erro if len(ms) == 0 { return nil, "", errNotFound } - zlog.Debug(ctx). - Strs("paths", ms). - Msg("found possible buildinfo Dockerfile(s)") + slog.DebugContext(ctx, "found possible buildinfo Dockerfile(s)", "paths", ms) var p string for _, m := range ms { if strings.Count(m, "-") > 1 { @@ -242,9 +236,7 @@ func findLabels(ctx context.Context, sys fs.FS) (map[string]string, string, erro if p == "" { return nil, "", errNotFound } - zlog.Info(ctx). - Str("path", p). - Msg("found buildinfo Dockerfile") + slog.InfoContext(ctx, "found buildinfo Dockerfile", "path", p) f, err := sys.Open(p) if err != nil { return nil, "", err @@ -287,7 +279,6 @@ func (s *reposcanner) Kind() string { return "repository" } // Scan implements [indexer.RepositoryScanner]. func (s *reposcanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Repository, error) { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/rhcc/reposcanner.Scan") sys, err := l.FS() if err != nil { return nil, fmt.Errorf("rhcc: unable to open layer: %w", err) @@ -299,7 +290,6 @@ func (s *reposcanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircor if len(ms) == 0 { return nil, nil } - zlog.Debug(ctx). - Msg("found buildinfo Dockerfile") + slog.DebugContext(ctx, "found buildinfo Dockerfile") return []*claircore.Repository{&GoldRepo}, nil } diff --git a/rhel/rhcc/scanner_test.go b/rhel/rhcc/scanner_test.go index 30e03199c..f38fd9af8 100644 --- a/rhel/rhcc/scanner_test.go +++ b/rhel/rhcc/scanner_test.go @@ -2,7 +2,6 @@ package rhcc import ( "archive/tar" - "context" "encoding/json" "io" "net/http" @@ -13,7 +12,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" @@ -21,7 +19,7 @@ import ( func TestContainerScanner(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) clairSourceContainer := &claircore.Package{ Name: "quay-clair-container", Version: "v3.5.5-4", @@ -191,7 +189,7 @@ func TestContainerScanner(t *testing.T) { }) for _, tt := range table { t.Run(tt.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) mod := test.Modtime(t, tt.Dockerfile) a.GenerateLayer(t, tt.Name, mod, func(t testing.TB, w *os.File) { dockerfile, err := os.Open(tt.Dockerfile) diff --git a/rhel/rhel.go b/rhel/rhel.go index 7ae0a0cfd..2f442e616 100644 --- a/rhel/rhel.go +++ b/rhel/rhel.go @@ -13,8 +13,7 @@ import ( "errors" "fmt" "io/fs" - - "github.com/quay/zlog" + "log/slog" ) // GetContentManifest reads and parses the content manifest file from the layer. @@ -35,9 +34,7 @@ func getContentManifest(ctx context.Context, sys fs.FS) (*contentManifest, error return nil, nil } p := ms[0] - zlog.Debug(ctx). - Str("manifest-path", p). - Msg("found content manifest file") + slog.DebugContext(ctx, "found content manifest file", "manifest-path", p) b, err := fs.ReadFile(sys, p) if err != nil { return nil, fmt.Errorf("rhel: unable to read %q: %w", p, err) @@ -48,10 +45,9 @@ func getContentManifest(ctx context.Context, sys fs.FS) (*contentManifest, error switch { case errors.Is(err, nil): case errors.As(err, &syntaxErr): - zlog.Warn(ctx). - Str("manifest-path", p). - Err(err). - Msg("could not unmarshal content_manifests file") + slog.WarnContext(ctx, "could not unmarshal content_manifests file", + "manifest-path", p, + "reason", err) return nil, nil default: return nil, err diff --git a/rhel/rhel_test.go b/rhel/rhel_test.go index f61c55127..b76b92811 100644 --- a/rhel/rhel_test.go +++ b/rhel/rhel_test.go @@ -1,7 +1,6 @@ package rhel import ( - "context" "os" "strings" "testing" @@ -9,12 +8,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/quay/claircore" "github.com/quay/claircore/test" - "github.com/quay/zlog" ) func TestGetContentManifest(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) tests := []struct { name string @@ -53,7 +50,7 @@ func TestGetContentManifest(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) // Create a layer from the test data f, err := os.Open(tt.tarPath) diff --git a/rhel/vex/fetcher.go b/rhel/vex/fetcher.go index 0ab3b5615..552ec50ac 100644 --- a/rhel/vex/fetcher.go +++ b/rhel/vex/fetcher.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "log/slog" "net/http" "net/url" "path" @@ -18,7 +19,6 @@ import ( "time" "github.com/klauspost/compress/snappy" - "github.com/quay/zlog" "github.com/quay/claircore/internal/httputil" "github.com/quay/claircore/internal/zreader" @@ -36,14 +36,13 @@ var ( // - Make a request to discover the latest archive endpoint. // - Make a HEAD request to archive endpoint to get the last-modified header. // - Save the last-modified time in the fingerprint's requestTime. -// 2. Process the changes.csv file, requesting and appending the entries that changed since the finderprint's requestTime. -// 3. Process the deletions.csv file, processing the entries that changed since the finderprint's requestTime. +// 2. Process the changes.csv file, requesting and appending the entries that changed since the fingerprint's requestTime. +// 3. Process the deletions.csv file, processing the entries that changed since the fingerprint's requestTime. // 4. If we need to process entire archive, request the archive data and append the entries that have not been changed or deleted. // // This helps to ensure that we only persist one copy of an advisory in the worst possible case. In most cases, // after the initial load, the number of processed files should be very small. func (u *Updater) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/vex/Updater.Fetch") fp, err := parseFingerprint(hint) if err != nil { return nil, hint, err @@ -59,16 +58,14 @@ func (u *Updater) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCl var success bool defer func() { if err := cw.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close snappy writer") + slog.WarnContext(ctx, "unable to close snappy writer", "reason", err) } if _, err := f.Seek(0, io.SeekStart); err != nil { - zlog.Warn(ctx). - Err(err). - Msg("unable to seek file back to start") + slog.WarnContext(ctx, "unable to seek file back to start", "reason", err) } if !success { if err := f.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + slog.WarnContext(ctx, "unable to close spool", "reason", err) } } }() @@ -84,9 +81,7 @@ func (u *Updater) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCl if err != nil { return nil, hint, fmt.Errorf("could not get compressed file URL: %w", err) } - zlog.Debug(ctx). - Str("url", compressedURL.String()). - Msg("got compressed URL") + slog.DebugContext(ctx, "got compressed URL", "url", compressedURL) fp.requestTime, err = u.getLastModified(ctx, compressedURL) if err != nil { @@ -178,10 +173,9 @@ func (u *Updater) Fetch(ctx context.Context, hint driver.Fingerprint) (io.ReadCl return nil, hint, fmt.Errorf("error reading tar contents: %w", err) } - zlog.Debug(ctx). - Str("updater", u.Name()). - Int("entries written", entriesWritten). - Msg("finished writing compressed data to spool") + slog.DebugContext(ctx, "finished writing compressed data to spool", + "updater", u.Name(), + "entries written", entriesWritten) } fp.version = updaterVersion @@ -353,7 +347,7 @@ func (u *Updater) processChanges(ctx context.Context, w io.Writer, fp *fingerpri if err != nil { return fmt.Errorf("error reading from buffer: %w", err) } - zlog.Debug(ctx).Str("url", advisoryURI.String()).Msg("copying body to file") + slog.DebugContext(ctx, "copying body to file", "url", advisoryURI) err = json.Compact(&bc, buf.Bytes()) if err != nil { return fmt.Errorf("error compressing JSON: %w", err) @@ -434,7 +428,7 @@ func (u *Updater) processDeletions(ctx context.Context, w io.Writer, fp *fingerp deletedJSON, err := createDeletedJSON(cvePath) if err != nil { - zlog.Warn(ctx).Err(err).Msg("error creating JSON object denoting deletion") + slog.WarnContext(ctx, "error creating JSON object denoting deletion", "reason", err) } bc.Write(deletedJSON) bc.WriteByte('\n') diff --git a/rhel/vex/fetcher_test.go b/rhel/vex/fetcher_test.go index 588a0ec70..ac5026e70 100644 --- a/rhel/vex/fetcher_test.go +++ b/rhel/vex/fetcher_test.go @@ -3,18 +3,17 @@ package vex import ( "bufio" "bytes" - "context" "testing" "github.com/klauspost/compress/snappy" - "github.com/quay/zlog" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" "github.com/quay/claircore/toolkit/types/csaf" ) func TestFactory(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) root, c := ServeSecDB(t, "testdata/server.txtar") fac := &Factory{} err := fac.Configure(ctx, func(v any) error { diff --git a/rhel/vex/parser.go b/rhel/vex/parser.go index 39a0b803c..d624728c6 100644 --- a/rhel/vex/parser.go +++ b/rhel/vex/parser.go @@ -7,13 +7,13 @@ import ( "errors" "fmt" "io" + "log/slog" "math" "strings" "unique" "github.com/klauspost/compress/snappy" "github.com/package-url/packageurl-go" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/pkg/rhctag" @@ -32,7 +32,6 @@ func (u *Updater) Parse(ctx context.Context, contents io.ReadCloser) ([]*clairco // DeltaParse implements [driver.DeltaUpdater]. func (u *Updater) DeltaParse(ctx context.Context, contents io.ReadCloser) ([]*claircore.Vulnerability, []string, error) { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/vex/Updater.DeltaParse") // This map is needed for deduplication purposes, the compressed CSAF data will include // entries that have been subsequently updated in the changes. out := map[string][]*claircore.Vulnerability{} @@ -59,7 +58,6 @@ func (u *Updater) DeltaParse(ctx context.Context, contents io.ReadCloser) ([]*cl selfLink = r.URL } } - ctx = zlog.ContextWithValues(ctx, "link", selfLink) creator := newCreator(name, selfLink, c, pc, rc) for _, v := range c.Vulnerabilities { // Create vuln here, there should always be one vulnerability @@ -252,7 +250,8 @@ func extractProductNames(prodRef, relatesToProdRef string, comps []string, c *cs func (c *creator) knownAffectedVulnerabilities(ctx context.Context, v csaf.Vulnerability, protoVulnFunc func() *claircore.Vulnerability) ([]*claircore.Vulnerability, error) { ranger := newRanger() unrelatedProductIDs := []string{} - debugEnabled := zlog.Debug(ctx).Enabled() + log := slog.With("link", c.vulnLink) + debugEnabled := log.Enabled(ctx, slog.LevelDebug) out := []*claircore.Vulnerability{} for _, pc := range v.ProductStatus["known_affected"] { pkgName, modName, repoName, err := walkRelationships(pc, c.c) @@ -272,16 +271,13 @@ func (c *creator) knownAffectedVulnerabilities(ctx context.Context, v csaf.Vulne repoProd := c.pc.Get(repoName, c.c) if repoProd == nil { - zlog.Warn(ctx). - Str("prod", repoName). - Msg("could not find product in product tree") + // Should never get here, error in data + log.WarnContext(ctx, "could not find product in product tree", "prod", repoName) continue } cpeHelper, ok := repoProd.IdentificationHelper["cpe"] if !ok { - zlog.Warn(ctx). - Str("prod", repoName). - Msg("could not find cpe helper type in product") + log.WarnContext(ctx, "could not find cpe helper type in product", "prod", repoName) continue } @@ -291,10 +287,7 @@ func (c *creator) knownAffectedVulnerabilities(ctx context.Context, v csaf.Vulne modProd := c.pc.Get(modName, c.c) modName, err = createPackageModule(modProd) if err != nil { - zlog.Warn(ctx). - Str("module", modName). - Err(err). - Msg("could not create package module") + log.WarnContext(ctx, "could not create package module", "module", modName, "reason", err) } } @@ -302,9 +295,7 @@ func (c *creator) knownAffectedVulnerabilities(ctx context.Context, v csaf.Vulne compProd := c.pc.Get(pkgName, c.c) if compProd == nil { // Should never get here, error in data - zlog.Warn(ctx). - Str("pkg", pkgName). - Msg("could not find package in product tree") + log.WarnContext(ctx, "could not find package in product tree", "pkg", pkgName) continue } vuln := protoVulnFunc() @@ -321,29 +312,22 @@ func (c *creator) knownAffectedVulnerabilities(ctx context.Context, v csaf.Vulne if ok { purl, err := packageurl.FromString(purlHelper) if err != nil { - zlog.Warn(ctx). - Str("purlHelper", purlHelper). - Err(err). - Msg("could not parse PURL") + log.WarnContext(ctx, "could not parse pURL", "reason", err, "purl", purlHelper) continue } if !checkPURL(purl) { continue } if pn, err := extractPackageName(purl); err != nil { - zlog.Warn(ctx). - Str("purl", purl.String()). - Err(err). - Msg("could not extract package name from pURL") + log.WarnContext(ctx, "error extracting package name from pURL", + "reason", err, "purl", purl) } else { pkgName = pn } if modName, err = componentPURLToModuleName(purl); err != nil { - zlog.Warn(ctx). - Str("purl", purl.String()). - Err(err). - Msg("invalid rpmmod in component pURL") + log.WarnContext(ctx, "invalid rpmmod in component pURL", + "reason", err, "purl", purl) continue } @@ -351,10 +335,8 @@ func (c *creator) knownAffectedVulnerabilities(ctx context.Context, v csaf.Vulne vuln.Repo = c.rc.Get(wfn, rhcc.RepositoryKey) vuln.Range, err = ranger.add(pkgName, vuln.FixedInVersion) if err != nil { - zlog.Warn(ctx). - Str("FixedInVersion", vuln.FixedInVersion). - Err(err). - Msg("could not parse version into range") + log.WarnContext(ctx, "could not parse version into range", + "reason", err, "FixedInVersion", vuln.FixedInVersion) continue } } @@ -387,9 +369,7 @@ func (c *creator) knownAffectedVulnerabilities(ctx context.Context, v csaf.Vulne } ranger.resetLowest() if len(unrelatedProductIDs) > 0 { - zlog.Debug(ctx). - Strs("product_ids", unrelatedProductIDs). - Msg("skipped unrelatable product_ids") + log.DebugContext(ctx, "skipped unrelatable product_ids", "product_ids", unrelatedProductIDs) } return out, nil @@ -424,7 +404,7 @@ func newRanger() *ranger { // to the fixedInVersion. Add also saves the lowest range per packageName that it's seen. // This allows resetLowest() to zero out the lowest values we saw per packageName. func (r *ranger) add(packageName, fixedInVersion string) (*claircore.Range, error) { - var rng = &claircore.Range{} + rng := &claircore.Range{} if fixedInVersion == "" { zeroVer := &rhctag.Version{} @@ -463,7 +443,8 @@ func (r *ranger) resetLowest() { func (c *creator) fixedVulnerabilities(ctx context.Context, v csaf.Vulnerability, protoVulnFunc func() *claircore.Vulnerability) ([]*claircore.Vulnerability, error) { ranger := newRanger() unrelatedProductIDs := []string{} - debugEnabled := zlog.Debug(ctx).Enabled() + log := slog.With("link", c.vulnLink) + debugEnabled := log.Enabled(ctx, slog.LevelDebug) for _, pc := range v.ProductStatus["fixed"] { pkgName, modName, repoName, err := walkRelationships(pc, c.c) if err != nil { @@ -478,16 +459,12 @@ func (c *creator) fixedVulnerabilities(ctx context.Context, v csaf.Vulnerability repoProd := c.pc.Get(repoName, c.c) if repoProd == nil { // Should never get here, error in data - zlog.Warn(ctx). - Str("prod", repoName). - Msg("could not find product in product tree") + log.WarnContext(ctx, "could not find product in product tree", "prod", repoName) continue } cpeHelper, ok := repoProd.IdentificationHelper["cpe"] if !ok { - zlog.Warn(ctx). - Str("prod", repoName). - Msg("could not find cpe helper type in product") + log.WarnContext(ctx, "could not find cpe helper type in product", "prod", repoName) continue } @@ -497,33 +474,24 @@ func (c *creator) fixedVulnerabilities(ctx context.Context, v csaf.Vulnerability modProd := c.pc.Get(modName, c.c) modName, err = createPackageModule(modProd) if err != nil { - zlog.Warn(ctx). - Str("module", modName). - Err(err). - Msg("could not create package module") + log.WarnContext(ctx, "could not create package module", "module", modName, "reason", err) } } compProd := c.pc.Get(pkgName, c.c) if compProd == nil { // Should never get here, error in data - zlog.Warn(ctx). - Str("pkg", pkgName). - Msg("could not find package in product tree") + log.WarnContext(ctx, "could not find package in product tree", "pkg", pkgName) continue } purlHelper, ok := compProd.IdentificationHelper["purl"] if !ok { - zlog.Warn(ctx). - Str("pkg", pkgName). - Msg("could not find purl helper type in product") + log.WarnContext(ctx, "could not find purl helper type in product", "pkg", pkgName) continue } purl, err := packageurl.FromString(purlHelper) if err != nil { - zlog.Warn(ctx). - Str("purl", purlHelper). - Msg("could not parse PURL") + log.WarnContext(ctx, "could not parse pURL", "reason", err, "purl", purlHelper) continue } if !checkPURL(purl) { @@ -531,25 +499,19 @@ func (c *creator) fixedVulnerabilities(ctx context.Context, v csaf.Vulnerability } fixedIn, err := extractFixedInVersion(purl) if err != nil { - zlog.Warn(ctx). - Str("purl", purl.String()). - Err(err). - Msg("error extracting fixed_in version from pURL") + log.WarnContext(ctx, "error extracting fixed_in version from pURL", + "reason", err, "purl", purl) continue } packageName, err := extractPackageName(purl) if err != nil { - zlog.Warn(ctx). - Str("purl", purl.String()). - Err(err). - Msg("error extracting package name from pURL") + log.WarnContext(ctx, "error extracting package name from pURL", + "reason", err, "purl", purl) continue } if modName, err = componentPURLToModuleName(purl); err != nil { - zlog.Warn(ctx). - Str("purl", purl.String()). - Err(err). - Msg("invalid rpmmod in component pURL") + log.WarnContext(ctx, "invalid rpmmod in component pURL", + "reason", err, "purl", purl) continue } @@ -583,10 +545,8 @@ func (c *creator) fixedVulnerabilities(ctx context.Context, v csaf.Vulnerability vuln.Repo = c.rc.Get(wfn, rhcc.RepositoryKey) vuln.Range, err = ranger.add(packageName, vuln.FixedInVersion) if err != nil { - zlog.Warn(ctx). - Str("FixedInVersion", vuln.FixedInVersion). - Err(err). - Msg("could not parse version into range") + log.WarnContext(ctx, "could not parse version into range", + "reason", err, "FixedInVersion", vuln.FixedInVersion) continue } default: @@ -617,9 +577,7 @@ func (c *creator) fixedVulnerabilities(ctx context.Context, v csaf.Vulnerability } ranger.resetLowest() if len(unrelatedProductIDs) > 0 { - zlog.Debug(ctx). - Strs("product_ids", unrelatedProductIDs). - Msg("skipped unrelatable product_ids") + log.DebugContext(ctx, "skipped unrelatable product_ids", "product_ids", unrelatedProductIDs) } out := make([]*claircore.Vulnerability, len(c.fixedVulns)) diff --git a/rhel/vex/parser_test.go b/rhel/vex/parser_test.go index af86f26c5..11311779e 100644 --- a/rhel/vex/parser_test.go +++ b/rhel/vex/parser_test.go @@ -2,7 +2,6 @@ package vex import ( "bytes" - "context" "encoding/json" "errors" "io" @@ -15,10 +14,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/klauspost/compress/snappy" "github.com/package-url/packageurl-go" - "github.com/quay/zlog" "github.com/quay/claircore" + "github.com/quay/claircore/test" "github.com/quay/claircore/toolkit/types/cpe" "github.com/quay/claircore/toolkit/types/csaf" ) @@ -373,7 +372,6 @@ func TestEscapeCPE(t *testing.T) { func TestParseCompare(t *testing.T) { t.Parallel() - ctx := context.Background() url, err := url.Parse(BaseURL) if err != nil { t.Error(err) @@ -415,7 +413,7 @@ func TestParseCompare(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f, err := os.Open(tc.filename) if err != nil { t.Fatalf("failed to open test data file %s: %v", tc.filename, err) @@ -458,7 +456,6 @@ func TestParseCompare(t *testing.T) { func TestParse(t *testing.T) { t.Parallel() - ctx := context.Background() url, err := url.Parse(BaseURL) if err != nil { t.Error(err) @@ -520,7 +517,7 @@ func TestParse(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) // Build a snappy stream consisting of compacted JSON blobs from each file, // newline-separated to simulate JSONL input across multiple files. diff --git a/rhel/vex/updater.go b/rhel/vex/updater.go index 3db969136..36285164a 100644 --- a/rhel/vex/updater.go +++ b/rhel/vex/updater.go @@ -4,13 +4,12 @@ import ( "context" "errors" "fmt" + "log/slog" "net/http" "net/url" "strings" "time" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" ) @@ -163,8 +162,6 @@ type UpdaterConfig struct { // Configure implements driver.Configurable. func (u *Updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, "component", "rhel/vex/Updater.Configure") - var cfg UpdaterConfig if err := f(&cfg); err != nil { return err @@ -178,9 +175,7 @@ func (u *Updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c * return err } u.url = url - zlog.Info(ctx). - Str("updater", u.Name()). - Msg("configured url") + slog.InfoContext(ctx, "configured url", "updater", u.Name()) u.client = c return nil diff --git a/rpm/packagescanner.go b/rpm/packagescanner.go index 0bd2e0304..6fd7d381d 100644 --- a/rpm/packagescanner.go +++ b/rpm/packagescanner.go @@ -6,10 +6,9 @@ import ( "errors" "fmt" "io/fs" + "log/slog" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/internal/rpm" @@ -56,12 +55,8 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) (out []*cla } defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "rpm/Scanner.Scan", - "version", ps.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := layer.FS() if err != nil { @@ -74,8 +69,7 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) (out []*cla }() for db := range dbs { err = func() error { - ctx := zlog.ContextWithValues(ctx, "db", db.String()) - zlog.Debug(ctx).Msg("examining database") + slog.DebugContext(ctx, "examining database", "db", db) db, dbErr := rpm.OpenDB(ctx, sys, db) switch { case dbErr == nil: diff --git a/rpm/packagescanner_test.go b/rpm/packagescanner_test.go index a2a464b3d..4f14237a9 100644 --- a/rpm/packagescanner_test.go +++ b/rpm/packagescanner_test.go @@ -1,7 +1,6 @@ package rpm import ( - "context" "os" "path/filepath" "slices" @@ -9,7 +8,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/internal/wart" @@ -25,7 +23,7 @@ import ( ////go:generate fetch -o testdata/package/ubi9_nodejs.txtar ubi9/nodejs-20 func TestPackageDetection(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) ms, err := filepath.Glob("testdata/package/*.txtar") if err != nil { panic("programmer error") // static glob @@ -66,7 +64,7 @@ func TestPackageDetection(t *testing.T) { arches[img.Archtecture] = struct{}{} t.Run(img.Archtecture, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) m, err := ar.Manifest(img.ID) if err != nil { t.Fatal(err) @@ -119,7 +117,7 @@ func TestPackageDetection(t *testing.T) { } func TestDanglingSymlink(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) desc := claircore.LayerDescription{ Digest: test.RandomSHA256Digest(t).String(), URI: "file:///dev/null", @@ -154,7 +152,6 @@ func TestDanglingSymlink(t *testing.T) { } func TestLayer(t *testing.T) { - ctx := context.Background() ents, err := os.ReadDir(`testdata/layers`) if err != nil { t.Fatal(err) @@ -173,7 +170,7 @@ func TestLayer(t *testing.T) { continue } t.Run(n, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) f, err := os.Open(filepath.Join(`testdata/layers`, n)) if err != nil { t.Fatal(err) @@ -203,7 +200,7 @@ func TestLayer(t *testing.T) { } func TestLayerDoesNotExist(t *testing.T) { - ctx := zlog.Test(t.Context(), t) + ctx := test.Logging(t) desc := &claircore.LayerDescription{ Digest: test.RandomSHA256Digest(t).String(), diff --git a/ruby/matcher.go b/ruby/matcher.go index 8f42df9ba..c1b18d772 100644 --- a/ruby/matcher.go +++ b/ruby/matcher.go @@ -2,10 +2,9 @@ package ruby import ( "context" + "log/slog" "net/url" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" ) @@ -41,10 +40,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v // Parse the package first. If it cannot be parsed, it cannot properly be analyzed for vulnerabilities. rv, err := NewVersion(record.Package.Version) if err != nil { - zlog.Warn(ctx). - Str("package", record.Package.Name). - Str("version", record.Package.Version). - Msg("unable to parse ruby gem package version") + slog.WarnContext(ctx, "unable to parse ruby gem package version", + "package", record.Package.Name, + "version", record.Package.Version) return false, err } @@ -58,10 +56,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v if introduced != "" { iv, err := NewVersion(introduced) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", introduced). - Msg("unable to parse ruby gem introduced version") + slog.WarnContext(ctx, "unable to parse ruby gem introduced version", + "package", vuln.Package.Name, + "version", introduced) return false, err } // If the package's version is less than the introduced version, it's not vulnerable. @@ -76,10 +73,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v case fixedVersion != "": fv, err := NewVersion(fixedVersion) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", fixedVersion). - Msg("unable to parse ruby gem fixed version") + slog.WarnContext(ctx, "unable to parse ruby gem fixed version", + "package", vuln.Package.Name, + "version", fixedVersion) return false, err } // The package is affected if its version is less than the fixed version. @@ -87,10 +83,9 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v case lastAffected != "": la, err := NewVersion(lastAffected) if err != nil { - zlog.Warn(ctx). - Str("package", vuln.Package.Name). - Str("version", lastAffected). - Msg("unable to parse ruby gem last_affected version") + slog.WarnContext(ctx, "unable to parse ruby gem last_affected version", + "package", vuln.Package.Name, + "version", lastAffected) return false, err } // The package is affected if its version is less than or equal to the last affected version. diff --git a/ruby/matcher_test.go b/ruby/matcher_test.go index a23a2ffe4..a4b9222f2 100644 --- a/ruby/matcher_test.go +++ b/ruby/matcher_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/test" @@ -183,5 +182,6 @@ func TestVulnerable(t *testing.T) { } func TestMatcher(t *testing.T) { - test.RunMatcherTests(zlog.Test(context.Background(), t), t, "testdata/matcher", new(Matcher)) + ctx := test.Logging(t) + test.RunMatcherTests(ctx, t, "testdata/matcher", new(Matcher)) } diff --git a/ruby/packagescanner.go b/ruby/packagescanner.go index 93100ef0e..c7da5fa17 100644 --- a/ruby/packagescanner.go +++ b/ruby/packagescanner.go @@ -7,13 +7,12 @@ import ( "context" "fmt" "io/fs" + "log/slog" "path/filepath" "regexp" "runtime/trace" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" "github.com/quay/claircore/rpm" @@ -82,12 +81,8 @@ func (*Scanner) Kind() string { return "package" } func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*claircore.Package, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "ruby/Scanner.Scan", - "version", ps.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") if err := ctx.Err(); err != nil { return nil, err } @@ -109,9 +104,7 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco } for _, g := range gs { if set.Contains(g) { - zlog.Debug(ctx). - Str("path", g). - Msg("file path determined to be of RPM origin") + slog.DebugContext(ctx, "file path determined to be of RPM origin", "path", g) continue } f, err := sys.Open(g) @@ -132,17 +125,14 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco } } if err := scanner.Err(); err != nil { - zlog.Warn(ctx). - Err(err). - Str("path", g). - Msg("unable to read metadata, skipping") + slog.WarnContext(ctx, "unable to read metadata, skipping", + "reason", err, + "path", g) continue } if name == "" || version == "" { - zlog.Warn(ctx). - Str("path", g). - Msg("couldn't parse name or version, skipping") + slog.WarnContext(ctx, "couldn't parse name or version, skipping", "path", g) continue } @@ -172,14 +162,7 @@ func trim(s string) string { func gems(ctx context.Context, sys fs.FS) (out []string, err error) { return out, fs.WalkDir(sys, ".", func(p string, d fs.DirEntry, err error) error { - ev := zlog.Debug(ctx). - Str("file", p) - var success bool - defer func() { - if !success { - ev.Discard().Send() - } - }() + attrs := []slog.Attr{slog.String("file", p)} switch { case err != nil: return err @@ -189,12 +172,11 @@ func gems(ctx context.Context, sys fs.FS) (out []string, err error) { case strings.HasPrefix(filepath.Base(p), ".wh."): return nil case gemspecPath.MatchString(p): - ev = ev.Str("kind", "gem") + attrs = append(attrs, slog.String("kind", "gem")) default: return nil } - ev.Msg("found package") - success = true + slog.LogAttrs(ctx, slog.LevelDebug, "found package", attrs...) out = append(out, p) return nil }) diff --git a/ruby/packagescanner_test.go b/ruby/packagescanner_test.go index fc5bb422c..9704f7183 100644 --- a/ruby/packagescanner_test.go +++ b/ruby/packagescanner_test.go @@ -1,11 +1,9 @@ package ruby_test import ( - "context" "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/ruby" @@ -13,8 +11,6 @@ import ( ) func TestScanRemote(t *testing.T) { - ctx := zlog.Test(context.Background(), t) - type testcase struct { Name string Ref test.LayerRef @@ -138,7 +134,7 @@ func TestScanRemote(t *testing.T) { for _, tc := range table { t.Run(tc.Name, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) l := test.RealizeLayer(ctx, t, tc.Ref) var scanner ruby.Scanner diff --git a/sbom/spdx/encoder.go b/sbom/spdx/encoder.go index a5134ac76..e2ba77ebf 100644 --- a/sbom/spdx/encoder.go +++ b/sbom/spdx/encoder.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "log/slog" "runtime/debug" "slices" "strconv" @@ -18,7 +19,6 @@ import ( "github.com/quay/claircore" "github.com/quay/claircore/purl" "github.com/quay/claircore/sbom" - "github.com/quay/zlog" ) // Version describes the SPDX version to target. @@ -209,7 +209,7 @@ func (e *Encoder) parseIndexReport(ctx context.Context, ir *claircore.IndexRepor purl, err := e.PURLConverter.Generate(ctx, r) switch { case err != nil: - zlog.Warn(ctx).Err(err).Msg("failed to generate PURL") + slog.WarnContext(ctx, "failed to generate PURL", "reason", err) default: pkg.PackageExternalReferences = append(pkg.PackageExternalReferences, &v2_3.PackageExternalReference{ Category: "PACKAGE_MANAGER", diff --git a/scanner/pkgconfig/scanner.go b/scanner/pkgconfig/scanner.go index 0a1ee5ed2..53e8ea655 100644 --- a/scanner/pkgconfig/scanner.go +++ b/scanner/pkgconfig/scanner.go @@ -12,12 +12,11 @@ import ( "fmt" "io" "io/fs" + "log/slog" "os" "path/filepath" "runtime/trace" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -49,12 +48,8 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco } defer trace.StartRegion(ctx, "Scanner.Scan").End() trace.Log(ctx, "layer", layer.Hash.String()) - ctx = zlog.ContextWithValues(ctx, - "component", "scanner/pkgconfig/Scanner.Scan", - "version", ps.Version(), - "layer", layer.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := layer.FS() if err != nil { @@ -71,9 +66,8 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco case filepath.Ext(d.Name()) != ".pc": return nil } - zlog.Debug(ctx). - Str("path", p). - Msg("found possible pkg-config file") + log := slog.With("path", p) + log.DebugContext(ctx, "found possible pkg-config file") f, err := sys.Open(p) if err != nil { return err @@ -84,9 +78,7 @@ func (ps *Scanner) Scan(ctx context.Context, layer *claircore.Layer) ([]*clairco switch { case errors.Is(nil, err): case errors.Is(errInvalid, err): // skip - zlog.Info(ctx). - Str("path", p). - Msg("invalid pkg-config file") + slog.InfoContext(ctx, "invalid pkg-config file") return nil default: return err diff --git a/suse/distributionscanner.go b/suse/distributionscanner.go index cae924edb..05a1c34e0 100644 --- a/suse/distributionscanner.go +++ b/suse/distributionscanner.go @@ -4,10 +4,10 @@ import ( "bytes" "context" "fmt" + "log/slog" "runtime/trace" "github.com/Masterminds/semver" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -64,15 +64,11 @@ func (*DistributionScanner) Kind() string { return scannerKind } // If the files are found but all regexp fail to match an empty slice is returned. func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "suse/DistributionScanner.Scan", - "version", ds.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") files, err := l.Files(osReleasePath, suseReleasePath) if err != nil { - zlog.Debug(ctx).Msg("didn't find an os-release or SuSE-release") + slog.DebugContext(ctx, "didn't find an os-release or SuSE-release") return nil, nil } for _, buff := range files { @@ -91,7 +87,7 @@ func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([] func (ds *DistributionScanner) parse(ctx context.Context, buff *bytes.Buffer) *claircore.Distribution { kv, err := osrelease.Parse(ctx, buff) if err != nil { - zlog.Warn(ctx).Err(err).Msg("malformed os-release file") + slog.WarnContext(ctx, "malformed os-release file", "reason", err) return nil } cpeName, cpeOK := kv["CPE_NAME"] @@ -101,13 +97,13 @@ func (ds *DistributionScanner) parse(ctx context.Context, buff *bytes.Buffer) *c // Instead of regexing through, we can grab the CPE. c, err := cpe.Unbind(cpeName) if err != nil { - zlog.Warn(ctx).Err(err).Msg("could not unbind CPE") + slog.WarnContext(ctx, "could not unbind CPE", "reason", err) return nil } d, err := cpeToDist(c) if err != nil { - zlog.Warn(ctx).Err(err).Msg("error converting cpe to distribution") + slog.WarnContext(ctx, "error converting cpe to distribution", "reason", err) return nil } diff --git a/suse/factory.go b/suse/factory.go index 8f70875c7..62737aad0 100644 --- a/suse/factory.go +++ b/suse/factory.go @@ -3,6 +3,7 @@ package suse import ( "context" "fmt" + "log/slog" "net/http" "net/url" "regexp" @@ -10,7 +11,6 @@ import ( "sync" "github.com/Masterminds/semver" - "github.com/quay/zlog" "golang.org/x/net/html" "github.com/quay/claircore" @@ -37,20 +37,16 @@ type Factory struct { // UpdaterSet implements [driver.UpdaterSetFactory]. func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { - ctx = zlog.ContextWithValues(ctx, "component", "suse/Factory.UpdaterSet") us := driver.NewUpdaterSet() if f.c == nil { - zlog.Info(ctx). - Msg("unconfigured") + slog.InfoContext(ctx, "unconfigured") return us, nil } req, err := http.NewRequestWithContext(ctx, http.MethodGet, f.base.String(), nil) if err != nil { return us, fmt.Errorf("suse: unable to construct request: %w", err) } - zlog.Debug(ctx). - Stringer("url", f.base). - Msg("making request") + slog.DebugContext(ctx, "making request", "url", f.base) res, err := f.c.Do(req) if err != nil { return us, fmt.Errorf("suse: error requesting %q: %w", f.base.String(), err) diff --git a/suse/factory_test.go b/suse/factory_test.go index 22aca61b5..7ab76c838 100644 --- a/suse/factory_test.go +++ b/suse/factory_test.go @@ -1,16 +1,17 @@ package suse import ( - "context" "net/http" "net/url" "testing" - "github.com/quay/zlog" + "github.com/quay/claircore/test" + "github.com/quay/claircore/test/integration" ) func TestFactory(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + integration.Skip(t) + ctx := test.Logging(t) u, _ := url.Parse(base) f := &Factory{ c: http.DefaultClient, diff --git a/suse/parser.go b/suse/parser.go index e53cde0e0..eca750efb 100644 --- a/suse/parser.go +++ b/suse/parser.go @@ -5,9 +5,9 @@ import ( "encoding/xml" "fmt" "io" + "log/slog" "github.com/quay/goval-parser/oval" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/internal/xmlutil" @@ -18,9 +18,7 @@ import ( var _ driver.Parser = (*Updater)(nil) func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "suse/Updater.Parse") - zlog.Info(ctx).Msg("starting parse") + slog.InfoContext(ctx, "starting parse") defer r.Close() root := oval.Root{} dec := xml.NewDecoder(r) @@ -28,7 +26,7 @@ func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln if err := dec.Decode(&root); err != nil { return nil, fmt.Errorf("suse: unable to decode OVAL document: %w", err) } - zlog.Debug(ctx).Msg("xml decoded") + slog.DebugContext(ctx, "xml decoded") protoVulns := func(def oval.Definition) ([]*claircore.Vulnerability, error) { return []*claircore.Vulnerability{ { diff --git a/test/bisect/main_test.go b/test/bisect/main_test.go index ff054675b..dbe0f1c96 100644 --- a/test/bisect/main_test.go +++ b/test/bisect/main_test.go @@ -7,6 +7,7 @@ import ( "flag" "fmt" "hash/fnv" + "log/slog" "net/http" "net/http/httptest" "os" @@ -21,8 +22,6 @@ import ( "text/template" "time" - "github.com/quay/zlog" - "github.com/rs/zerolog" "golang.org/x/sync/errgroup" "github.com/quay/claircore" @@ -217,11 +216,11 @@ func escapeImage(i string) string { // Setup does a grip of test setup work, returning a context that will cancel on // interrupt and a server set up to serve files from "dir". func setup(ctx context.Context, t *testing.T, dir string) (context.Context, *httptest.Server) { - l := zerolog.Nop() + h := slog.DiscardHandler if stderr { - l = zerolog.New(zerolog.NewConsoleWriter()) + h = slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{}) } - zlog.Set(&l) + slog.SetDefault(slog.New(h)) for _, v := range []struct { Tmpl **template.Template @@ -243,7 +242,7 @@ func setup(ctx context.Context, t *testing.T, dir string) (context.Context, *htt ctx, done := signal.NotifyContext(ctx, os.Interrupt) t.Cleanup(done) - if err := os.MkdirAll(dir, 0755); err != nil { + if err := os.MkdirAll(dir, 0o755); err != nil { t.Fatal(err) } fsrv := http.FileServer(http.Dir(dir)) diff --git a/test/logging.go b/test/logging.go new file mode 100644 index 000000000..50c8bacbe --- /dev/null +++ b/test/logging.go @@ -0,0 +1,148 @@ +package test + +import ( + "context" + "fmt" + "log/slog" + "os" + "path/filepath" + "runtime/debug" + "strings" + "sync" + "testing" + "time" + + "github.com/quay/claircore/toolkit/log" +) + +var ( + // Setup installs the test log handler exactly once. + setup = sync.OnceFunc(func() { + slog.SetDefault(slog.New(new(handler))) + }) + + // Getwd caches [os.Getwd], since it may be called for every [slog.Record]. + getwd = sync.OnceValue(func() string { + dir, err := os.Getwd() + if err != nil { + panic(err) + } + return dir + }) + + // Modname caches the main module name, since it may be needed for every + // [slog.Record]. + modname = sync.OnceValue(func() string { + if info, ok := debug.ReadBuildInfo(); ok { + return info.Main.Path + "/" + } + return "" + }) +) + +type ctxKey struct{} + +var logHandler ctxKey + +var _ slog.Handler = (handler)(nil) + +// DeferredOp is a closure used with [handler] that allows +// [slog.Handler.WithAttrs] and [slog.Handler.WithGroup] to work by deferring +// the call until the concrete [slog.Handler] implementation can be retrieved +// from a [context.Context]. +// +// When a Handler isn't in the Context passed to the Enabled or Handle methods, +// the call is a no-op. +type deferredOp func(slog.Handler) slog.Handler + +// Handler implements [slog.Handler] by extracting a "real" [slog.Handler] from +// the a [context.Context]. +type handler []deferredOp + +// Enabled implements [slog.Handler]. +func (h handler) Enabled(ctx context.Context, l slog.Level) bool { + v := ctx.Value(logHandler) + if v == nil { + return false // ??? + } + lh, ok := v.(slog.Handler) + if !ok { + return false // ??? + } + return lh.Enabled(ctx, l) +} + +// Handle implements [slog.Handler]. +func (h handler) Handle(ctx context.Context, r slog.Record) error { + v := ctx.Value(logHandler) + if v == nil { + return nil // ??? + } + lh, ok := v.(slog.Handler) + if !ok { + return nil // ??? + } + for _, op := range h { + lh = op(lh) + } + if v, ok := ctx.Value(log.AttrsKey).(slog.Value); ok { + r.AddAttrs(v.Group()...) + } + return lh.Handle(ctx, r) +} + +// WithAttrs implements [slog.Handler]. +func (h handler) WithAttrs(attrs []slog.Attr) slog.Handler { + return append(h, func(h slog.Handler) slog.Handler { + return h.WithAttrs(attrs) + }) +} + +// WithGroup implements [slog.Handler]. +func (h handler) WithGroup(name string) slog.Handler { + return append(h, func(h slog.Handler) slog.Handler { + return h.WithGroup(name) + }) +} + +// Logging returns a [context.Context] that's set up to make the default +// [slog.Logger] defer output to the provided [testing.TB] output. +func Logging(t testing.TB, parent ...context.Context) context.Context { + setup() + var ctx context.Context + if len(parent) > 0 { + ctx = parent[0] + } else { + // Don't use the test Context: users should pass that in if that's what + // they want. + ctx = context.Background() + } + start := time.Now() + w := logOutput(t) + h := slog.NewTextHandler(w, &slog.HandlerOptions{ + AddSource: true, + Level: slog.LevelDebug, + ReplaceAttr: func(g []string, a slog.Attr) slog.Attr { + if g != nil { + return a + } + switch a.Key { + case "time": + dur := time.Since(start) + return slog.String("time", "+"+dur.String()) + case "source": + src := a.Value.Any().(*slog.Source) + if src.Function != "" { + return slog.String("source", strings.TrimPrefix(src.Function, modname())) + } + f := src.File + if r, err := filepath.Rel(getwd(), f); err == nil && r != "" { + f = r + } + return slog.String("source", fmt.Sprintf("%s:%d", f, src.Line)) + } + return a + }, + }) + return context.WithValue(ctx, logHandler, h) +} diff --git a/test/logging_go124.go b/test/logging_go124.go new file mode 100644 index 000000000..ceb1dab26 --- /dev/null +++ b/test/logging_go124.go @@ -0,0 +1,36 @@ +//go:build !go1.25 + +package test + +import ( + "bufio" + "io" + "os" + "path/filepath" + "testing" +) + +func logOutput(t testing.TB) io.Writer { + d := t.TempDir() + n := filepath.Join(d, "output") + t.Cleanup(func() { + f, err := os.Open(n) + if err != nil { + t.Error(err) + return + } + defer f.Close() + s := bufio.NewScanner(f) + for s.Scan() { + t.Log(s.Text()) + } + if err := s.Err(); err != nil { + t.Error(err) + } + }) + w, err := os.Create(n) + if err != nil { + t.Fatal(err) + } + return w +} diff --git a/test/logging_go125.go b/test/logging_go125.go new file mode 100644 index 000000000..a90ea43d9 --- /dev/null +++ b/test/logging_go125.go @@ -0,0 +1,12 @@ +//go:build go1.25 + +package test + +import ( + "io" + "testing" +) + +func logOutput(t testing.TB) io.Writer { + return t.Output() +} diff --git a/test/matcher.go b/test/matcher.go index 38777c2e4..fb7f0fbbd 100644 --- a/test/matcher.go +++ b/test/matcher.go @@ -17,7 +17,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "go.uber.org/mock/gomock" "golang.org/x/tools/txtar" @@ -58,9 +57,6 @@ type MatcherGetCall struct { // [Jq]: https://jqlang.github.io/jq/ func RunMatcherTests(ctx context.Context, t *testing.T, dir string, matchers ...driver.Matcher) { t.Helper() - if ctx == nil { - ctx = zlog.Test(context.Background(), t) - } ms, err := filepath.Glob(filepath.Join(dir, "*.txtar")) if err != nil { @@ -73,7 +69,7 @@ func RunMatcherTests(ctx context.Context, t *testing.T, dir string, matchers ... n := filepath.Base(m) n = strings.TrimSuffix(n, filepath.Ext(n)) t.Run(n, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := Logging(t, ctx) t.Logf("loading txtar: %#q", m) ar, err := txtar.ParseFile(m) diff --git a/test/packagescanner.go b/test/packagescanner.go index 88dc64dc1..23bfc6c2c 100644 --- a/test/packagescanner.go +++ b/test/packagescanner.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/indexer" @@ -46,7 +45,7 @@ func (tc ScannerTestcase) Digest() claircore.Digest { func (tc ScannerTestcase) Run(ctx context.Context) func(*testing.T) { sort.Slice(tc.Want, pkgSort(tc.Want)) return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := Logging(t, ctx) l := tc.getLayer(ctx, t) got, err := tc.Scanner.Scan(ctx, l) @@ -69,7 +68,7 @@ func (tc ScannerTestcase) Run(ctx context.Context) func(*testing.T) { func (tc ScannerTestcase) RunSubset(ctx context.Context, n int) func(*testing.T) { sort.Slice(tc.Want, pkgSort(tc.Want)) return func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := Logging(t, ctx) l := tc.getLayer(ctx, t) got, err := tc.Scanner.Scan(ctx, l) diff --git a/test/periodic/enricher_test.go b/test/periodic/enricher_test.go index b1f470161..69b4b19db 100644 --- a/test/periodic/enricher_test.go +++ b/test/periodic/enricher_test.go @@ -6,14 +6,13 @@ import ( "testing" "time" - "github.com/quay/zlog" - "github.com/quay/claircore/enricher/cvss" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" ) func TestCVSS(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) e := &cvss.Enricher{} err := e.Configure(ctx, func(any) error { return nil }, pkgClient) if err != nil { diff --git a/test/periodic/rpm_test.go b/test/periodic/rpm_test.go index 8f1e12254..ed1be28c3 100644 --- a/test/periodic/rpm_test.go +++ b/test/periodic/rpm_test.go @@ -12,7 +12,6 @@ import ( "time" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/rhel" @@ -133,7 +132,7 @@ func (doc hydraDoc) Run(dir string) func(*testing.T) { } return func(t *testing.T) { t.Parallel() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) try := 1 Retry: diff --git a/test/periodic/updater_test.go b/test/periodic/updater_test.go index fb6b64849..f74019644 100644 --- a/test/periodic/updater_test.go +++ b/test/periodic/updater_test.go @@ -7,8 +7,6 @@ import ( "time" "github.com/quay/claircore" - "github.com/quay/zlog" - "github.com/quay/claircore/alpine" "github.com/quay/claircore/aws" "github.com/quay/claircore/debian" @@ -17,6 +15,7 @@ import ( "github.com/quay/claircore/photon" "github.com/quay/claircore/rhel/vex" "github.com/quay/claircore/suse" + "github.com/quay/claircore/test" "github.com/quay/claircore/ubuntu" "github.com/quay/claircore/updater/osv" ) @@ -27,16 +26,16 @@ func noopConfigure(_ any) error { } func TestAWS(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) set, err := aws.UpdaterSet(ctx) if err != nil { t.Fatal() } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestAlpine(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) fac, err := alpine.NewFactory(ctx) if err != nil { t.Fatal() @@ -49,11 +48,11 @@ func TestAlpine(t *testing.T) { if err != nil { t.Fatal(err) } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestDebian(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) fac, err := debian.NewFactory(ctx) if err != nil { t.Fatal() @@ -66,29 +65,29 @@ func TestDebian(t *testing.T) { if err != nil { t.Fatal(err) } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestOracle(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) set, err := oracle.UpdaterSet(ctx) if err != nil { t.Fatal(err) } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestPhoton(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) set, err := photon.UpdaterSet(ctx) if err != nil { t.Fatal(err) } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestRHELVEX(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) fac := new(vex.Factory) err := fac.Configure(ctx, noopConfigure, pkgClient) if err != nil { @@ -98,11 +97,11 @@ func TestRHELVEX(t *testing.T) { if err != nil { t.Fatal(err) } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestSUSE(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) fac := new(suse.Factory) err := fac.Configure(ctx, noopConfigure, pkgClient) if err != nil { @@ -113,11 +112,11 @@ func TestSUSE(t *testing.T) { if err != nil { t.Fatal() } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestUbuntu(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) fac, err := ubuntu.NewFactory(ctx) if err != nil { t.Fatal(err) @@ -130,11 +129,11 @@ func TestUbuntu(t *testing.T) { if err != nil { t.Fatal(err) } - runUpdaterSet(ctx, t, set) + runUpdaterSet(t, set) } func TestOSV(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) fac := &osv.Factory{} if err := fac.Configure(ctx, noopConfigure, pkgClient); err != nil { t.Fatal(err) @@ -143,14 +142,14 @@ func TestOSV(t *testing.T) { if err != nil { t.Fatal(err) } - runUpdaterSet(ctx, t, us) + runUpdaterSet(t, us) } -func runUpdaterSet(ctx context.Context, t *testing.T, set driver.UpdaterSet) { +func runUpdaterSet(t *testing.T, set driver.UpdaterSet) { t.Helper() for _, u := range set.Updaters() { t.Run(u.Name(), func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) if cfg, ok := u.(driver.Configurable); ok { err := cfg.Configure(ctx, noopConfigure, pkgClient) if err != nil { diff --git a/test/rhel/rhcc_matcher_integration_test.go b/test/rhel/rhcc_matcher_integration_test.go index acd64a224..5cafa6bf0 100644 --- a/test/rhel/rhcc_matcher_integration_test.go +++ b/test/rhel/rhcc_matcher_integration_test.go @@ -1,7 +1,6 @@ package rhel import ( - "context" "encoding/json" "fmt" "io" @@ -9,8 +8,6 @@ import ( "path/filepath" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/datastore/postgres" match_engine "github.com/quay/claircore/internal/matcher" @@ -19,6 +16,7 @@ import ( "github.com/quay/claircore/pkg/ctxlock/v2" "github.com/quay/claircore/rhel/rhcc" "github.com/quay/claircore/rhel/vex" + "github.com/quay/claircore/test" "github.com/quay/claircore/test/integration" testpostgres "github.com/quay/claircore/test/postgres" ) @@ -67,7 +65,7 @@ func TestMatcherIntegration(t *testing.T) { } integration.NeedDB(t) - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) pool := testpostgres.TestMatcherDB(ctx, t) store := postgres.NewMatcherStore(pool) locks, err := ctxlock.New(ctx, pool) diff --git a/test/rpmtest/archive.go b/test/rpmtest/archive.go index 85b442e9f..03ed6ced8 100644 --- a/test/rpmtest/archive.go +++ b/test/rpmtest/archive.go @@ -16,7 +16,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/quay/zlog" "golang.org/x/tools/txtar" "github.com/quay/claircore" @@ -209,7 +208,7 @@ func (a *Archive) Tests( arches[img.Archtecture] = struct{}{} t.Run(img.Archtecture, func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) m, err := a.Manifest(img.ID) if err != nil { t.Fatal(err) diff --git a/ubuntu/distributionscanner.go b/ubuntu/distributionscanner.go index 95ec100f1..4dc513017 100644 --- a/ubuntu/distributionscanner.go +++ b/ubuntu/distributionscanner.go @@ -7,11 +7,10 @@ import ( "fmt" "io" "io/fs" + "log/slog" "runtime/trace" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -45,12 +44,8 @@ func (*DistributionScanner) Kind() string { return scannerKind } // Scan implements [indexer.DistributionScanner]. func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) { defer trace.StartRegion(ctx, "Scanner.Scan").End() - ctx = zlog.ContextWithValues(ctx, - "component", "ubuntu/DistributionScanner.Scan", - "version", ds.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { return nil, fmt.Errorf("ubuntu: unable to open layer: %w", err) diff --git a/ubuntu/updater.go b/ubuntu/updater.go index 8060ecf33..726c9cea6 100644 --- a/ubuntu/updater.go +++ b/ubuntu/updater.go @@ -6,11 +6,11 @@ import ( "encoding/xml" "fmt" "io" + "log/slog" "net/http" "net/url" "github.com/quay/goval-parser/oval" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/internal/xmlutil" @@ -43,9 +43,6 @@ func (u *updater) Name() string { // Configure implements [driver.Configurable]. func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, - "component", "ubuntu/Updater.Configure", - "updater", u.Name()) u.c = c var cfg UpdaterConfig @@ -58,8 +55,7 @@ func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c * return err } u.url = cfg.URL - zlog.Info(ctx). - Msg("configured database URL") + slog.InfoContext(ctx, "configured database URL") } if cfg.UseBzip2 != nil { u.useBzip2 = *cfg.UseBzip2 @@ -79,9 +75,7 @@ type UpdaterConfig struct { // Fetch implements [driver.Updater]. func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "ubuntu/Updater.Fetch", - "database", u.url) + log := slog.With("database", u.url) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.url, nil) if err != nil { @@ -101,7 +95,7 @@ func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io switch resp.StatusCode { case http.StatusOK: if fp := string(fingerprint); fp == "" || fp != resp.Header.Get("etag") { - zlog.Info(ctx).Msg("fetching latest oval database") + log.InfoContext(ctx, "fetching latest oval database") break } fallthrough @@ -120,7 +114,7 @@ func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io defer func() { if !success { if err := f.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close spool") + log.WarnContext(ctx, "unable to close spool", "reason", err) } } }() @@ -136,15 +130,13 @@ func (u *updater) Fetch(ctx context.Context, fingerprint driver.Fingerprint) (io } success = true - zlog.Info(ctx).Msg("fetched latest oval database successfully") + log.InfoContext(ctx, "fetched latest oval database successfully") return f, driver.Fingerprint(fp), err } // Parse implements [driver.Updater]. func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "ubuntu/Updater.Parse") - zlog.Info(ctx).Msg("starting parse") + slog.InfoContext(ctx, "starting parse") defer r.Close() root := oval.Root{} dec := xml.NewDecoder(r) @@ -152,7 +144,7 @@ func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln if err := dec.Decode(&root); err != nil { return nil, fmt.Errorf("ubuntu: unable to decode OVAL document: %w", err) } - zlog.Debug(ctx).Msg("xml decoded") + slog.DebugContext(ctx, "xml decoded") nameLookupFunc := func(def oval.Definition, name *oval.DpkgName) []string { // if the dpkginfo_object>name field has a var_ref it indicates @@ -167,7 +159,7 @@ func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln } _, i, err := root.Variables.Lookup(name.Ref) if err != nil { - zlog.Error(ctx).Err(err).Msg("could not lookup variable id") + slog.WarnContext(ctx, "could not lookup variable id", "reason", err) return ns } consts := root.Variables.ConstantVariables[i] diff --git a/ubuntu/updaterset.go b/ubuntu/updaterset.go index 42ffd4ed5..da9e59282 100644 --- a/ubuntu/updaterset.go +++ b/ubuntu/updaterset.go @@ -4,13 +4,13 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "net/http" "net/url" "path" "strings" "sync" - "github.com/quay/zlog" "golang.org/x/sync/errgroup" "github.com/quay/claircore" @@ -67,8 +67,6 @@ type FactoryConfig struct { // Configure implements [driver.Configurable]. func (f *Factory) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, - "component", "ubuntu/Factory.Configure") var cfg FactoryConfig if err := cf(&cfg); err != nil { return err @@ -84,8 +82,7 @@ func (f *Factory) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c if err != nil { return fmt.Errorf("ubuntu: unable to parse provided URL: %w", err) } - zlog.Info(ctx). - Msg("configured URL") + slog.InfoContext(ctx, "configured URL") } n := defaultName if cfg.Name != "" { @@ -106,9 +103,6 @@ func (f *Factory) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c // UpdaterSet implements [driver.UpdaterSetFactory] func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "ubuntu/Factory.UpdaterSet") - set := driver.NewUpdaterSet() req, err := http.NewRequestWithContext(ctx, http.MethodGet, f.api, nil) if err != nil { @@ -146,7 +140,7 @@ func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { e := &series.Entries[i] mkDist(e.Version, e.Name) if !e.Active { - zlog.Debug(ctx).Str("release", e.Name).Msg("release not active") + slog.DebugContext(ctx, "release not active", "release", e.Name) continue } select { @@ -175,10 +169,9 @@ func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { switch res.StatusCode { case http.StatusOK: case http.StatusNotFound: - zlog.Debug(ctx). - Str("name", e.Name). - Str("version", e.Version). - Msg("OVAL database missing, skipping") + slog.DebugContext(ctx, "OVAL database missing, skipping", + "name", e.Name, + "version", e.Version) continue default: return fmt.Errorf("ubuntu: unexpected status requesting %q: %q", url, res.Status) @@ -210,7 +203,7 @@ func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { } if len(f.force) != 0 { - zlog.Info(ctx).Msg("configuring manually specified updaters") + slog.InfoContext(ctx, "configuring manually specified updaters") ns := make([]string, 0, len(f.force)) for _, p := range f.force { u := &updater{ @@ -221,12 +214,12 @@ func (f *Factory) UpdaterSet(ctx context.Context) (driver.UpdaterSet, error) { } if err := set.Add(u); err != nil { // Already exists, skip. - zlog.Debug(ctx).Err(err).Msg("skipping updater") + slog.DebugContext(ctx, "skipping updater", "reason", err) continue } ns = append(ns, u.Name()) } - zlog.Info(ctx).Strs("updaters", ns).Msg("added specified updaters") + slog.InfoContext(ctx, "added specified updaters", "updaters", ns) } return set, nil diff --git a/updater/offline_test.go b/updater/offline_test.go index 0d1ed83ee..effb69d20 100644 --- a/updater/offline_test.go +++ b/updater/offline_test.go @@ -3,7 +3,6 @@ package updater import ( "archive/zip" "bytes" - "context" "encoding/json" "io" "net/http" @@ -13,16 +12,15 @@ import ( "path/filepath" "testing" - "github.com/quay/zlog" "go.uber.org/mock/gomock" + "github.com/quay/claircore/test" mock_updater "github.com/quay/claircore/test/mock/updater" mock_driver "github.com/quay/claircore/test/mock/updater/driver/v1" driver "github.com/quay/claircore/updater/driver/v1" ) func TestOffline(t *testing.T) { - ctx := context.Background() vs := &driver.ParsedVulnerabilities{ Updater: t.Name(), Vulnerability: []driver.Vulnerability{{}}, @@ -40,7 +38,7 @@ func TestOffline(t *testing.T) { defer spool.Close() t.Run("Fetch", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) ctl := gomock.NewController(t) n := path.Dir(t.Name()) @@ -76,7 +74,7 @@ func TestOffline(t *testing.T) { }) t.Run("Parse", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) ctl := gomock.NewController(t) n := path.Dir(t.Name()) @@ -124,7 +122,7 @@ func TestOffline(t *testing.T) { }) t.Run("Prev", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) ctl := gomock.NewController(t) n := path.Dir(t.Name()) if _, err := spool.Seek(0, io.SeekStart); err != nil { diff --git a/updater/offline_v1.go b/updater/offline_v1.go index 7f8d03a40..1305336bd 100644 --- a/updater/offline_v1.go +++ b/updater/offline_v1.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "io/fs" + "log/slog" "os" "path" "runtime" @@ -15,7 +16,6 @@ import ( "time" "github.com/google/uuid" - "github.com/quay/zlog" "golang.org/x/sync/errgroup" "github.com/quay/claircore/updater/driver/v1" @@ -41,7 +41,7 @@ func (u *Updater) importV1(ctx context.Context, sys fs.FS) error { } defer func() { if err := f.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("error closing config.json") + slog.WarnContext(ctx, "error closing config.json", "reason", err) } }() if err := json.NewDecoder(f).Decode(&cfg); err != nil { @@ -52,9 +52,7 @@ func (u *Updater) importV1(ctx context.Context, sys fs.FS) error { if err != nil { return err } - zlog.Info(ctx). - Int("ct", len(us)). - Msg("got updaters") + slog.InfoContext(ctx, "got updaters", "count", len(us)) spool, err := os.CreateTemp(tmpDir, tmpPattern) if err != nil { @@ -63,22 +61,20 @@ func (u *Updater) importV1(ctx context.Context, sys fs.FS) error { defer func() { spoolname := spool.Name() if err := os.Remove(spoolname); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("unable to remove spool file") + slog.WarnContext(ctx, "unable to remove spool file", "filename", spoolname, "reason", err) } if err := spool.Close(); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("error closing spool file") + slog.WarnContext(ctx, "error closing spool file", "filename", spoolname, "reason", err) } }() for _, upd := range us { name := upd.Name - ctx := zlog.ContextWithValues(ctx, "updater", name) fi, err := fs.Stat(sys, name) switch { case errors.Is(err, nil): case errors.Is(err, fs.ErrNotExist): - zlog.Info(ctx). - Msg("no import, skipping") + slog.InfoContext(ctx, "no import, skipping", "updater", name) continue default: return err @@ -128,13 +124,13 @@ func (u *Updater) importV1(ctx context.Context, sys fs.FS) error { if err := u.store.UpdateVulnerabilities(ctx, ref, name, fp, res.Vulnerabilities); err != nil { return err } - zlog.Info(ctx).Stringer("ref", ref).Msg("updated vulnerabilites") + slog.InfoContext(ctx, "updated vulnerabilites", "ref", ref) } if len(res.Enrichments) != 0 { if err := u.store.UpdateEnrichments(ctx, ref, name, fp, res.Enrichments); err != nil { return err } - zlog.Info(ctx).Stringer("ref", ref).Msg("updated enrichments") + slog.InfoContext(ctx, "updated enrichments", "ref", ref) } } @@ -161,9 +157,7 @@ func (u *Updater) exportV1(ctx context.Context, z *zip.Writer, prev fs.FS) error if err != nil { return err } - zlog.Info(ctx). - Int("ct", len(us)). - Msg("got updaters") + slog.InfoContext(ctx, "got updaters", "count", len(us)) // WaitGroup for the worker goroutines. var wg sync.WaitGroup @@ -218,7 +212,7 @@ func (u *Updater) exportV1(ctx context.Context, z *zip.Writer, prev fs.FS) error defer wg.Done() for upd := range feed { name := upd.Name - ctx := zlog.ContextWithValues(ctx, "updater", name) + log := slog.With("updater", name) // Zips have to be written serially, so we spool the fetcher // output to disk, then seek back to the start so it's ready to // read. @@ -229,29 +223,29 @@ func (u *Updater) exportV1(ctx context.Context, z *zip.Writer, prev fs.FS) error // can't do much to recover from. spool, err := os.CreateTemp(tmpDir, tmpPattern) if err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to create spool file") + log.WarnContext(ctx, "unable to create spool file", "reason", err) continue } spoolname := spool.Name() fp, err := u.fetchOne(ctx, upd, pfps[name], spool) if err != nil { if err := os.Remove(spoolname); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("unable to remove spool file") + log.WarnContext(ctx, "unable to remove spool file", "filename", spoolname, "reason", err) } if err := spool.Close(); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("error closing spool file") + log.WarnContext(ctx, "error closing spool file", "filename", spoolname, "reason", err) } - zlog.Info(ctx).Err(err).Msg("updater error") + log.InfoContext(ctx, "updater error", "reason", err) continue } if _, err := spool.Seek(0, io.SeekStart); err != nil { if err := os.Remove(spoolname); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("unable to remove spool file") + log.WarnContext(ctx, "unable to remove spool file", "filename", spoolname, "reason", err) } if err := spool.Close(); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("error closing spool file") + log.WarnContext(ctx, "error closing spool file", "filename", spoolname, "reason", err) } - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("unable to seek to start") + log.WarnContext(ctx, "unable to seek to start", "filename", spoolname, "reason", err) continue } res <- &result{ @@ -274,10 +268,10 @@ func addUpdater(ctx context.Context, z *zip.Writer, now time.Time, r *result) er defer func() { fn := r.spool.Name() if err := os.Remove(fn); err != nil { - zlog.Warn(ctx).Err(err).Str("file", fn).Msg("unable to remove fetch spool") + slog.WarnContext(ctx, "unable to remove fetch spool", "reason", err, "file", fn) } if err := r.spool.Close(); err != nil { - zlog.Warn(ctx).Err(err).Str("file", fn).Msg("unable to close fetch spool") + slog.WarnContext(ctx, "unable to close fetch spool", "reason", err, "file", fn) } }() n := r.name @@ -327,10 +321,7 @@ func addUpdater(ctx context.Context, z *zip.Writer, now time.Time, r *result) er if _, err := io.Copy(w, r.spool); err != nil { return err } - zlog.Debug(ctx). - Stringer("ref", ref). - Str("name", n). - Msg("wrote out fetch results") + slog.DebugContext(ctx, "wrote out fetch results", "ref", ref, "name", n) return nil } diff --git a/updater/osv/osv.go b/updater/osv/osv.go index 1d7333c75..d6f4bf4aa 100644 --- a/updater/osv/osv.go +++ b/updater/osv/osv.go @@ -11,6 +11,7 @@ import ( "fmt" "io" "io/fs" + "log/slog" "net/http" "net/http/httputil" "net/url" @@ -20,7 +21,6 @@ import ( "github.com/Masterminds/semver" "github.com/quay/claircore/toolkit/types/cvss" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" @@ -74,7 +74,6 @@ type FactoryConfig struct { // Configure implements driver.Configurable. func (f *Factory) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, "component", "updater/osv/factory.Configure") var err error f.c = c @@ -100,12 +99,11 @@ func (f *Factory) Configure(ctx context.Context, cf driver.ConfigUnmarshaler, c } } - zlog.Debug(ctx).Msg("loaded incoming config") + slog.DebugContext(ctx, "loaded incoming config") return nil } func (f *Factory) UpdaterSet(ctx context.Context) (s driver.UpdaterSet, err error) { - ctx = zlog.ContextWithValues(ctx, "component", "updater/osv/factory.UpdaterSet") s = driver.NewUpdaterSet() if f.root == nil || f.c == nil { return s, errors.New("osv: factory not configured") // Purposely return an unhandleable error. @@ -117,10 +115,9 @@ func (f *Factory) UpdaterSet(ctx context.Context) (s driver.UpdaterSet, err erro defer func() { // This is an info print so operators can compare their allow list, // if need be. - zlog.Info(ctx). - Strs("ecosystems", stats.ecosystems). - Strs("skipped", stats.skipped). - Msg("ecosystems stats") + slog.InfoContext(ctx, "ecosystems stats", + "ecosystems", stats.ecosystems, + "skipped", stats.skipped) }() uri := *f.root @@ -156,9 +153,7 @@ func (f *Factory) UpdaterSet(ctx context.Context) (s driver.UpdaterSet, err erro } seen[e] = struct{}{} if _, ok := ignore[e]; ok { - zlog.Debug(ctx). - Str("ecosystem", e). - Msg("ignoring ecosystem") + slog.DebugContext(ctx, "ignoring ecosystem", "ecosystem", e) continue } stats.ecosystems = append(stats.ecosystems, e) @@ -170,10 +165,9 @@ func (f *Factory) UpdaterSet(ctx context.Context) (s driver.UpdaterSet, err erro uri := (*f.root).JoinPath(k, "all.zip") up := &updater{name: name, ecosystem: e, c: f.c, uri: uri} if err = s.Add(up); err != nil { - zlog.Error(ctx). - Str("ecosystem", e). - Err(err). - Msg("Failed to add updater to updaterset") + slog.WarnContext(ctx, "failed to add updater to updaterset", + "reason", err, + "ecosystem", e) continue } } @@ -188,9 +182,7 @@ func (f *Factory) UpdaterSet(ctx context.Context) (s driver.UpdaterSet, err erro err = fmt.Errorf("osv: unexpected response from %q: %v (request: %q) (body: %q)", res.Request.URL, res.Status, b, buf) } if err := res.Body.Close(); err != nil { - zlog.Info(ctx). - Err(err). - Msg("error closing ecosystems.txt response body") + slog.InfoContext(ctx, "error closing ecosystems.txt response body", "reason", err) } if err != nil { return s, err @@ -236,7 +228,6 @@ type UpdaterConfig struct { // Configure implements driver.Configurable. func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c *http.Client) error { - ctx = zlog.ContextWithValues(ctx, "component", "updater/osv/updater.Configure") var err error u.c = c @@ -250,28 +241,22 @@ func (u *updater) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c * return err } } - zlog.Debug(ctx).Msg("loaded incoming config") + slog.DebugContext(ctx, "loaded incoming config") return nil } // Fetcher implements driver.Updater. func (u *updater) Fetch(ctx context.Context, fp driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) { - ctx = zlog.ContextWithValues(ctx, "component", "updater/osv/updater.Fetch") - out, err := tmp.NewFile("", "osv.fetch.*") if err != nil { return nil, fp, err } defer func() { if _, err := out.Seek(0, io.SeekStart); err != nil { - zlog.Warn(ctx). - Err(err). - Msg("unable to seek file back to start") + slog.WarnContext(ctx, "unable to seek file back to start", "reason", err) } }() - zlog.Debug(ctx). - Str("filename", out.Name()). - Msg("opened temporary file for output") + slog.DebugContext(ctx, "opened temporary file for output", "filename", out.Name()) w := zip.NewWriter(out) defer w.Close() var ct int @@ -282,9 +267,7 @@ func (u *updater) Fetch(ctx context.Context, fp driver.Fingerprint) (io.ReadClos } req.Header.Set(`accept`, `application/zip`) if fp != "" { - zlog.Debug(ctx). - Str("hint", string(fp)). - Msg("using hint") + slog.DebugContext(ctx, "using hint", "hint", string(fp)) req.Header.Set("if-none-match", string(fp)) } @@ -304,26 +287,20 @@ func (u *updater) Fetch(ctx context.Context, fp driver.Fingerprint) (io.ReadClos if err != nil { break } - zlog.Debug(ctx). - Str("name", n). - Msg("wrote zip") + slog.DebugContext(ctx, "wrote zip", "name", n) ct++ case http.StatusNotModified: default: err = fmt.Errorf("osv: unexpected response from %q: %v", res.Request.URL.String(), res.Status) } if err := res.Body.Close(); err != nil { - zlog.Info(ctx). - Err(err). - Msg("error closing advisory zip response body") + slog.InfoContext(ctx, "error closing advisory zip response body", "reason", err) } if err != nil { return nil, fp, err } newEtag := res.Header.Get(`etag`) - zlog.Info(ctx). - Int("count", ct). - Msg("found updates") + slog.InfoContext(ctx, "found updates", "count", ct) if ct == 0 { return nil, fp, driver.Unchanged } @@ -333,11 +310,9 @@ func (u *updater) Fetch(ctx context.Context, fp driver.Fingerprint) (io.ReadClos // Fetcher implements driver.Updater. func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { - ctx = zlog.ContextWithValues(ctx, "component", "updater/osv/updater.Parse") ra, ok := r.(io.ReaderAt) if !ok { - zlog.Info(ctx). - Msg("spooling to disk") + slog.InfoContext(ctx, "spooling to disk") tf, err := tmp.NewFile("", `osv.parse.spool.*`) if err != nil { return nil, err @@ -388,9 +363,8 @@ func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln now := time.Now() ecs := newECS(u.Name()) for _, zf := range z.File { - ctx := zlog.ContextWithValues(ctx, "dumpfile", zf.Name) - zlog.Debug(ctx). - Msg("found file") + log := slog.With("dumpfile", zf.Name) + log.DebugContext(ctx, "found file") r, err := zf.Open() if err != nil { return nil, err @@ -411,7 +385,6 @@ func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln var skipped stats var ct int for _, zf := range z.File { - ctx := zlog.ContextWithValues(ctx, "advisory", strings.TrimSuffix(path.Base(zf.Name), ".json")) ct++ var a advisory rc, err := zf.Open() @@ -434,22 +407,18 @@ func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln default: } - if err := ecs.Insert(ctx, &skipped, name, &a); err != nil { + log := log.With("advisory", strings.TrimSuffix(path.Base(zf.Name), ".json")) + if err := ecs.Insert(ctx, log, &skipped, name, &a); err != nil { return nil, err } } - zlog.Debug(ctx). - Int("count", ct). - Msg("processed advisories") - zlog.Debug(ctx). - Strs("withdrawn", skipped.Withdrawn). - Strs("unaffected", skipped.Unaffected). - Strs("ignored", skipped.Ignored). - Msg("skipped advisories") - } - zlog.Info(ctx). - Int("count", ecs.Len()). - Msg("found vulnerabilities") + log.DebugContext(ctx, "processed advisories", "count", ct) + log.DebugContext(ctx, "skipped advisories", + "withdrawn", skipped.Withdrawn, + "unaffected", skipped.Unaffected, + "ignored", skipped.Ignored) + } + slog.InfoContext(ctx, "found vulnerabilities", "count", ecs.Len()) return ecs.Finalize(), nil } @@ -502,7 +471,7 @@ type rangeVer struct { ecosystemRange url.Values } -func (e *ecs) Insert(ctx context.Context, skipped *stats, name string, a *advisory) (err error) { +func (e *ecs) Insert(ctx context.Context, log *slog.Logger, skipped *stats, name string, a *advisory) (err error) { if a.GitOnly() { return nil } @@ -537,9 +506,7 @@ func (e *ecs) Insert(ctx context.Context, skipped *stats, name string, a *adviso continue } if err != nil { - zlog.Info(ctx). - Err(err). - Msg("odd cvss mangling result") + log.InfoContext(ctx, "odd cvss mangling result", "reason", err) continue } switch q { @@ -593,9 +560,7 @@ func (e *ecs) Insert(ctx context.Context, skipped *stats, name string, a *adviso // ignore, not going to fetch source. continue default: - zlog.Debug(ctx). - Str("type", r.Type). - Msg("odd range type") + log.DebugContext(ctx, "odd range type", "type", r.Type) } // This does some heavy assumptions about valid inputs. vs := &rangeVer{semverRange: &claircore.Range{}, ecosystemRange: url.Values{}} @@ -635,11 +600,10 @@ func (e *ecs) Insert(ctx context.Context, skipped *stats, name string, a *adviso } case ev.LastAffected != "" && len(af.Versions) != 0: // less than equal to // TODO(hank) Should be able to convert this to a "less than." - zlog.Info(ctx). - Str("which", "last_affected"). - Str("event", ev.LastAffected). - Strs("versions", af.Versions). - Msg("unsure how to interpret event") + log.InfoContext(ctx, "unsure how to interpret event", + "which", "last_affected", + "event", ev.LastAffected, + "versions", af.Versions) case ev.LastAffected != "": // less than equal to // This is semver, so we should be able to calculate the // "next" version: @@ -652,10 +616,9 @@ func (e *ecs) Insert(ctx context.Context, skipped *stats, name string, a *adviso vs.semverRange.Upper.Kind = `semver` vs.semverRange.Upper.V[0] = 65535 case ev.Limit != "": // Something arbitrary - zlog.Info(ctx). - Str("which", "limit"). - Str("event", ev.Limit). - Msg("unsure how to interpret event") + log.InfoContext(ctx, "unsure how to interpret event", + "which", "limit", + "event", ev.Limit) } case `ECOSYSTEM`: switch af.Package.Ecosystem { @@ -696,7 +659,7 @@ func (e *ecs) Insert(ctx context.Context, skipped *stats, name string, a *adviso } } if err != nil { - zlog.Warn(ctx).Err(err).Msg("event version error") + log.WarnContext(ctx, "event version error", "reason", err) } vers = append(vers, vs) } diff --git a/updater/osv/osv_test.go b/updater/osv/osv_test.go index bda1597bd..6b42f1bf5 100644 --- a/updater/osv/osv_test.go +++ b/updater/osv/osv_test.go @@ -4,12 +4,12 @@ import ( "archive/zip" "bufio" "bytes" - "context" "encoding/json" "errors" "fmt" "io" "io/fs" + "log/slog" "net/http" "net/http/httptest" "os" @@ -21,16 +21,16 @@ import ( "github.com/Masterminds/semver" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/quay/zlog" "github.com/quay/claircore" "github.com/quay/claircore/libvuln/driver" + "github.com/quay/claircore/test" ) func TestFetch(t *testing.T) { srv := httptest.NewServer(&apiStub{t, ""}) defer srv.Close() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) f := Factory{} cfgFunc := func(v any) error { @@ -110,7 +110,7 @@ func (a *apiStub) ServeHTTP(w http.ResponseWriter, r *http.Request) { func TestParse(t *testing.T) { srv := httptest.NewServer(&apiStub{t, ""}) defer srv.Close() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) f := Factory{} cfgFunc := func(v any) error { @@ -615,13 +615,13 @@ var cmpIgnore = cmpopts.IgnoreFields( claircore.Vulnerability{}, "ID", "Updater", "Description", "Severity", "NormalizedSeverity", "Package", "Repo") func TestInsert(t *testing.T) { - ctx := zlog.Test(context.Background(), t) - for _, tt := range insertTestCases { t.Run(tt.name, func(t *testing.T) { + ctx := test.Logging(t) ecs := newECS("test") - err := ecs.Insert(ctx, nil, "", tt.ad) + log := slog.Default() + err := ecs.Insert(ctx, log, nil, "", tt.ad) if err != nil { t.Error("got error Inserting advisory", err) } @@ -773,13 +773,13 @@ var severityTestCases = []struct { } func TestSeverityParsing(t *testing.T) { - ctx := zlog.Test(context.Background(), t) - for _, tt := range severityTestCases { t.Run(tt.name, func(t *testing.T) { + ctx := test.Logging(t) ecs := newECS("test") - err := ecs.Insert(ctx, nil, "", tt.a) + log := slog.Default() + err := ecs.Insert(ctx, log, nil, "", tt.a) if err != nil { t.Error("got error Inserting advisory", err) } @@ -793,7 +793,6 @@ func TestSeverityParsing(t *testing.T) { if v.Severity != tt.expectedSeverity { t.Errorf("expected severity %q but got %q", tt.expectedSeverity, v.Severity) } - }) } } @@ -875,12 +874,13 @@ func TestInsertLinksAliases(t *testing.T) { }, } - ctx := zlog.Test(context.Background(), t) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + ctx := test.Logging(t) + log := slog.Default() e := newECS("osv") var st stats - if err := (&e).Insert(ctx, &st, "pkg", &tt.adv); err != nil { + if err := (&e).Insert(ctx, log, &st, "pkg", &tt.adv); err != nil { t.Fatalf("Insert() error: %v", err) } if len(e.Vulnerability) == 0 { diff --git a/updater/registry.go b/updater/registry.go index 9578f0d29..dda500c29 100644 --- a/updater/registry.go +++ b/updater/registry.go @@ -3,13 +3,12 @@ package updater import ( "context" "errors" + "log/slog" "maps" "net/http" "strings" "sync" - "github.com/quay/zlog" - "github.com/quay/claircore/libvuln/driver" ) @@ -58,11 +57,10 @@ func Configure(ctx context.Context, fs map[string]driver.UpdaterSetFactory, cfg b.WriteString("updater: errors configuring factories:") for name, fac := range fs { - ev := zlog.Debug(ctx). - Str("factory", name) + msg := "factory unconfigurable" f, ok := fac.(driver.Configurable) if ok { - ev.Msg("configuring factory") + msg = "configuring factory" cf := cfg[name] if cf == nil { cf = noopConfig @@ -72,9 +70,8 @@ func Configure(ctx context.Context, fs map[string]driver.UpdaterSetFactory, cfg b.WriteString("\n\t") b.WriteString(err.Error()) } - } else { - ev.Msg("factory unconfigurable") } + slog.DebugContext(ctx, msg, "factory", name) } if errd { diff --git a/updater/updater.go b/updater/updater.go index 869156dc5..97d7722ef 100644 --- a/updater/updater.go +++ b/updater/updater.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "io/fs" + "log/slog" "net/http" "os" "runtime" @@ -16,9 +17,9 @@ import ( "sync" "github.com/google/uuid" - "github.com/quay/zlog" "golang.org/x/sync/errgroup" + "github.com/quay/claircore/toolkit/log" driver "github.com/quay/claircore/updater/driver/v1" ) @@ -54,15 +55,15 @@ func New(ctx context.Context, opts *Options) (*Updater, error) { } if opts.Locker == nil { - zlog.Warn(ctx).Msg("no locker passed, using process-local locking") + slog.WarnContext(ctx, "no locker passed, using process-local locking") u.locker = newLocalLocker() } if opts.Configs == nil { - zlog.Info(ctx).Msg("no updater configuration passed") + slog.InfoContext(ctx, "no updater configuration passed") u.configs = make(driver.Configs) } if opts.Factories == nil { - zlog.Warn(ctx).Msg("no updater factories provided, this may be a misconfiguration") + slog.WarnContext(ctx, "no updater factories provided, this may be a misconfiguration") } _, file, line, _ := runtime.Caller(1) @@ -171,16 +172,16 @@ func (u *Updater) Run(ctx context.Context, strict bool) error { defer wg.Done() spool, err := os.CreateTemp(tmpDir, tmpPattern) if err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to create spool file") + slog.WarnContext(ctx, "unable to create spool file", "reason", err) return err } spoolname := spool.Name() defer func() { if err := os.Remove(spoolname); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("unable to remove spool file") + slog.WarnContext(ctx, "unable to remove spool file", "filename", spoolname, "reason", err) } if err := spool.Close(); err != nil { - zlog.Warn(ctx).Str("filename", spoolname).Err(err).Msg("error closing spool file") + slog.WarnContext(ctx, "error closing spool file", "filename", spoolname, "reason", err) } }() var updErr *updaterError @@ -189,7 +190,7 @@ func (u *Updater) Run(ctx context.Context, strict bool) error { switch { case errors.Is(err, nil): case errors.As(err, &updErr): - zlog.Debug(ctx).Err(updErr).Msg("updater error") + slog.DebugContext(ctx, "updater error", "reason", updErr) errCh <- updErr.Unwrap() default: return err @@ -206,7 +207,7 @@ func (u *Updater) Run(ctx context.Context, strict bool) error { if strict { return errors.Join(errs...) } - zlog.Info(ctx).Errs("errors", errs).Msg("updater errors") + slog.InfoContext(ctx, "updater errors", "errors", errs) } return nil } @@ -229,7 +230,7 @@ func (u *Updater) updaters(ctx context.Context, cfg driver.Configs) ([]taggedUpd set, err = fac.Create(ctx, cfg[key]) }) if err != nil { - zlog.Info(ctx).Err(err).Msg("factory errored") + slog.InfoContext(ctx, "factory errored", "reason", err) continue } for _, upd := range set { @@ -238,11 +239,11 @@ func (u *Updater) updaters(ctx context.Context, cfg driver.Configs) ([]taggedUpd name = upd.Name() }) if strings.Contains(name, "/") { - zlog.Info(ctx).Str("updater", name).Msg("name contains invalid character: /") + slog.InfoContext(ctx, "name contains invalid character: /", "updater", name) continue } if _, ok := dedup[name]; ok { - zlog.Info(ctx).Str("updater", name).Msg("updater already exists") + slog.InfoContext(ctx, "updater already exists", "updater", name) continue } dedup[name] = struct{}{} @@ -258,17 +259,16 @@ func (u *Updater) updaters(ctx context.Context, cfg driver.Configs) ([]taggedUpd func (u *Updater) fetchOne(ctx context.Context, tu taggedUpdater, pfp driver.Fingerprint, out io.Writer) (fp driver.Fingerprint, err error) { name := tu.Name - ctx = zlog.ContextWithValues(ctx, "updater", name) - zlog.Info(ctx).Msg("fetch start") - defer zlog.Info(ctx).Msg("fetch done") + slog.InfoContext(ctx, "fetch start") + defer slog.InfoContext(ctx, "fetch done") lctx, done := u.locker.TryLock(ctx, name) defer done() if err := lctx.Err(); err != nil { if pErr := ctx.Err(); pErr != nil { - zlog.Debug(ctx).Err(err).Msg("parent context canceled") + slog.DebugContext(ctx, "parent context canceled", "reason", err) return fp, nil } - zlog.Info(ctx).Err(err).Msg("lock acquisition failed, skipping") + slog.InfoContext(ctx, "lock acquisition failed, skipping", "reason", err) return fp, err } ctx = lctx @@ -276,11 +276,11 @@ func (u *Updater) fetchOne(ctx context.Context, tu taggedUpdater, pfp driver.Fin zw := zip.NewWriter(out) defer func() { if err := zw.Close(); err != nil { - zlog.Warn(ctx).Err(err).Msg("unable to close zip writer") + slog.WarnContext(ctx, "unable to close zip writer", "reason", err) } }() if len(pfp) != 0 { - zlog.Debug(ctx).Str("fingerprint", string(pfp)).Msg("found previous fingerprint") + slog.DebugContext(ctx, "found previous fingerprint", "fingerprint", string(pfp)) } pprof.Do(ctx, pprof.Labels("task", "updater_fetch", "updater", name), func(ctx context.Context) { fp, err = tu.Updater.Fetch(ctx, zw, pfp, u.client) @@ -295,36 +295,33 @@ func (u *Updater) parseOne(ctx context.Context, tu taggedUpdater, in fs.FS) (*pa err error ) name := tu.Name - ctx = zlog.ContextWithValues(ctx, "updater", name) - zlog.Info(ctx).Msg("parse start") - defer zlog.Info(ctx).Msg("parse done") + ctx = log.With(ctx, "updater", name) + slog.InfoContext(ctx, "parse start") + defer slog.InfoContext(ctx, "parse done") pprof.Do(ctx, pprof.Labels("task", "updater_parse", "updater", name), func(ctx context.Context) { - ctx = zlog.ContextWithValues(ctx, "updater", name) upd := tu.Updater if p, ok := upd.(driver.VulnerabilityParser); ok { - zlog.Debug(ctx).Msg("implements VulnerabilityParser") + slog.DebugContext(ctx, "implements VulnerabilityParser") any = true res.Vulnerabilities, err = p.ParseVulnerability(ctx, in) if err != nil { return } - zlog.Debug(ctx). - Err(err). - Int("ct", len(res.Vulnerabilities.Vulnerability)). - Msg("found vulnerabilities") + slog.DebugContext(ctx, "found vulnerabilities", + "reason", err, + "ct", len(res.Vulnerabilities.Vulnerability)) } if p, ok := upd.(driver.EnrichmentParser); ok { - zlog.Debug(ctx).Msg("implements EnrichmentParser") + slog.DebugContext(ctx, "implements EnrichmentParser") any = true res.Enrichments, err = p.ParseEnrichment(ctx, in) if err != nil { return } - zlog.Debug(ctx). - Err(err). - Int("ct", len(res.Enrichments)). - Msg("found enrichments") + slog.DebugContext(ctx, "found enrichments", + "reason", err, + "ct", len(res.Enrichments)) } }) if !any { @@ -341,28 +338,27 @@ type parseResult struct { func (u *Updater) fetchAndParse(ctx context.Context, spool *os.File, pfps map[string]driver.Fingerprint, tu taggedUpdater) error { spoolname := spool.Name() name := tu.Name - ctx = zlog.ContextWithValues(ctx, "updater", name) if _, err := spool.Seek(0, io.SeekStart); err != nil { - zlog.Error(ctx).Str("filename", spoolname).Err(err).Msg("unable to seek to start") + slog.ErrorContext(ctx, "unable to seek to start", "filename", spoolname, "reason", err) return err } fp, err := u.fetchOne(ctx, tu, pfps[name], spool) switch { case errors.Is(err, nil): case errors.Is(err, driver.ErrUnchanged): - zlog.Debug(ctx).Msg("unchanged") + slog.DebugContext(ctx, "unchanged") return nil default: return updaterErr(err) } sz, err := spool.Seek(0, io.SeekCurrent) if err != nil { - zlog.Error(ctx).Str("filename", spoolname).Err(err).Msg("unable to seek spoolfile") + slog.ErrorContext(ctx, "unable to seek spoolfile", "filename", spoolname, "reason", err) return err } z, err := zip.NewReader(spool, sz) if err != nil { - zlog.Error(ctx).Str("filename", spoolname).Err(err).Msg("unable to create zip reader") + slog.ErrorContext(ctx, "unable to create zip reader", "filename", spoolname, "reason", err) return err } res, err := u.parseOne(ctx, tu, z) @@ -377,14 +373,14 @@ func (u *Updater) fetchAndParse(ctx context.Context, spool *os.File, pfps map[st if err != nil { return } - zlog.Info(ctx).Stringer("ref", ref).Msg("updated vulnerabilites") + slog.InfoContext(ctx, "updated vulnerabilites", "ref", ref) } if len(res.Enrichments) != 0 { err = u.store.UpdateEnrichments(ctx, ref, name, fp, res.Enrichments) if err != nil { return } - zlog.Info(ctx).Stringer("ref", ref).Msg("updated enrichments") + slog.InfoContext(ctx, "updated enrichments", "ref", ref) } }) if err != nil { diff --git a/updater/updater_test.go b/updater/updater_test.go index 44e4a57cb..028a055c6 100644 --- a/updater/updater_test.go +++ b/updater/updater_test.go @@ -15,18 +15,17 @@ import ( "testing" "github.com/google/uuid" - "github.com/quay/zlog" "go.uber.org/mock/gomock" + "github.com/quay/claircore/test" mock_updater "github.com/quay/claircore/test/mock/updater" mock_driver "github.com/quay/claircore/test/mock/updater/driver/v1" "github.com/quay/claircore/updater/driver/v1" ) func TestNew(t *testing.T) { - ctx := zlog.Test(context.Background(), t) t.Run("MissingStore", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) u, err := New(ctx, &Options{ Client: &http.Client{}, }) @@ -39,7 +38,7 @@ func TestNew(t *testing.T) { } }) t.Run("MissingClient", func(t *testing.T) { - ctx := zlog.Test(ctx, t) + ctx := test.Logging(t) u, err := New(ctx, &Options{ Store: mock_updater.NewMockStore(nil), }) @@ -132,7 +131,7 @@ func parseEnrich(_ context.Context, in fs.FS) (r []driver.EnrichmentRecord, err } func TestRun(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) ctl := gomock.NewController(t) n := path.Base(t.Name()) vs := &driver.ParsedVulnerabilities{ diff --git a/whiteout/resolver.go b/whiteout/resolver.go index d98cac5f1..fa913f60e 100644 --- a/whiteout/resolver.go +++ b/whiteout/resolver.go @@ -2,18 +2,15 @@ package whiteout import ( "context" + "log/slog" "path/filepath" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) -var ( - _ indexer.Resolver = (*Resolver)(nil) -) +var _ indexer.Resolver = (*Resolver)(nil) type Resolver struct{} @@ -40,11 +37,10 @@ func (r *Resolver) Resolve(ctx context.Context, ir *claircore.IndexReport, layer // layer. if f.Kind == claircore.FileKindWhiteout && ls.isChildOf(fileLayer, packageLayer) && fileIsDeleted(pkg.Filepath, f.Path) { packageDeleted = true - zlog.Debug(ctx). - Str("package name", pkg.Name). - Str("package file", pkg.Filepath). - Str("whiteout file", f.Path). - Msg("package determined to be deleted") + slog.DebugContext(ctx, "package determined to be deleted", + "package name", pkg.Name, + "package file", pkg.Filepath, + "whiteout file", f.Path) } } if !packageDeleted { diff --git a/whiteout/resolver_test.go b/whiteout/resolver_test.go index 0212435ad..ccf9cfa62 100644 --- a/whiteout/resolver_test.go +++ b/whiteout/resolver_test.go @@ -1,14 +1,12 @@ package whiteout import ( - "context" "crypto/sha256" "io" "testing" "github.com/quay/claircore" - - "github.com/quay/zlog" + "github.com/quay/claircore/test" ) func Digest(name string) claircore.Digest { @@ -260,7 +258,7 @@ func TestResolver(t *testing.T) { r := &Resolver{} for _, tc := range tests { t.Run(tc.Name, func(t *testing.T) { - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) report := r.Resolve(ctx, tc.Report, tc.Layers) if tc.LenPackage != len(report.Packages) { t.Fatalf("wrong number of packages: expected: %d got: %d", tc.LenPackage, len(report.Packages)) @@ -269,7 +267,6 @@ func TestResolver(t *testing.T) { t.Fatalf("wrong number of environments: expected: %d got: %d", tc.LenEnvs, len(report.Environments)) } }) - } } diff --git a/whiteout/scanner.go b/whiteout/scanner.go index a81a70091..bd5dce4a7 100644 --- a/whiteout/scanner.go +++ b/whiteout/scanner.go @@ -4,10 +4,9 @@ import ( "context" "fmt" "io/fs" + "log/slog" "strings" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/indexer" ) @@ -32,12 +31,8 @@ func (*Scanner) Version() string { return scannerVersion } func (*Scanner) Kind() string { return scannerKind } func (s *Scanner) Scan(ctx context.Context, l *claircore.Layer) ([]claircore.File, error) { - ctx = zlog.ContextWithValues(ctx, - "component", "whiteout/Scanner.Scan", - "version", s.Version(), - "layer", l.Hash.String()) - zlog.Debug(ctx).Msg("start") - defer zlog.Debug(ctx).Msg("done") + slog.DebugContext(ctx, "start") + defer slog.DebugContext(ctx, "done") sys, err := l.FS() if err != nil { return nil, fmt.Errorf("whiteout: unable to create fs: %w", err) diff --git a/whiteout/scanner_test.go b/whiteout/scanner_test.go index 754b8bab8..77a69f009 100644 --- a/whiteout/scanner_test.go +++ b/whiteout/scanner_test.go @@ -1,12 +1,9 @@ package whiteout import ( - "context" "os" "testing" - "github.com/quay/zlog" - "github.com/quay/claircore" "github.com/quay/claircore/test" ) @@ -17,7 +14,7 @@ var testScanner = &Scanner{} // layer in "name". func checkCount(t testing.TB, name string, ct int) { t.Helper() - ctx := zlog.Test(context.Background(), t) + ctx := test.Logging(t) lf, err := os.Open(name) if err != nil { t.Fatal(err)