refactor: replace log.Printf calls with Reporter interface#175
Conversation
Thread the Reporter to exportMetadata and replace direct log.Printf/Println calls in DoScan and exportMetadata with appropriate Reporter methods (Warnf, Errorf). This ensures library consumers using VoidReporter get complete silence. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Thread the Reporter from ScanContext to internal helper functions in Ruby (gemspec/gemfile enrichPackagesWithLocation), Python (pyprojectPackageCollector), and JavaScript (packageJSONDependencyMap.UnmarshalJSON) matchers. Update the pyproject test to use ExtractFromFileWithContext with a real Reporter instead of intercepting log.Writer(). Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add reporter field to ReachabilityJava struct and thread it from PerformReachabilityAnalysis. Remove redundant log in readFileContent since the error is already returned and handled by the caller. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f164bbfbd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if unmarshallErr != nil { | ||
| log.Printf("could not unmarshal %s, received error of %s", packageJSONContent, unmarshallErr) | ||
| if depMap.reporter != nil { | ||
| depMap.reporter.Errorf("could not unmarshal %s, received error of %s", packageJSONContent, unmarshallErr) |
There was a problem hiding this comment.
Use a warning for recoverable package.json parse failures
When a dependency section is valid JSON but not an object (for example "dependencies": []), this json.Unmarshal fails but UnmarshalJSON still returns nil and continues matching as before. Calling Errorf here marks the reporter as errored, and cmd/datadog-sbom-generator/main.go:67 turns any such mark into exit code 127 after an otherwise successful scan, so a recoverable matcher warning now fails the CLI; use a non-error reporting method for this path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. Changed Errorf to Warnf since this parse failure is recoverable — the matcher continues normally, so marking the scan as errored (and causing exit code 127 in the CLI) was incorrect.
…ailures - Errorf marks the scan as failed (exit code 127 in CLI); this parse failure is recoverable and should not fail the overall scan
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 317b5c7928
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| log.Printf( | ||
| "Multiple pyproject version ranges for dependency %q from %s collapse to the same unversioned PURL; CycloneDX output will keep the earliest source declaration. Saw ranges %q and %q\n", | ||
| c.reporter.Warnf( |
There was a problem hiding this comment.
Guard the reporter before warning
When PyProjectTOMLExtractor.Extract is used directly or via ExtractFromFileWithContext with a zero ScanContext/nil Reporter, a pyproject that declares two different ranges for the same dependency now panics here while trying to emit the conflict warning. This path previously used log.Printf and still returned packages, so library callers that only populate the context fields they need can regress from a successful parse to a nil-pointer crash; default to a VoidReporter or nil-check before calling Warnf.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
I guess it shouldn't happen? should we be more defensive?
There was a problem hiding this comment.
Fixed. Added reporter.Effective(r) helper that returns VoidReporter when nil, applied at construction time in createPackageJSONFile and pyprojectPackageCollector — the reporter field is now guaranteed non-nil, removing the need for nil-guards at call sites.
| val, err := vuln.ReachableSymbolLocations.MarshalToJSONString() | ||
| if err != nil { | ||
| log.Printf("failed to marshal reachable symbol locations into a JSON string: %s\n", err) | ||
| r.Errorf("failed to marshal reachable symbol locations into a JSON string: %s", err) |
There was a problem hiding this comment.
as we do continue in the case of an error, should we instead return as r.Warnf here?
There was a problem hiding this comment.
Sound good, you know better this logic
|
|
||
| log.Printf( | ||
| "Multiple pyproject version ranges for dependency %q from %s collapse to the same unversioned PURL; CycloneDX output will keep the earliest source declaration. Saw ranges %q and %q\n", | ||
| c.reporter.Warnf( |
There was a problem hiding this comment.
I guess it shouldn't happen? should we be more defensive?
- Add reporter.Effective(r) helper that returns VoidReporter when r is nil - Use it in createPackageJSONFile and pyprojectPackageCollector constructors so the reporter field is never nil after construction - Remove nil-guard at call site in UnmarshalJSON (now unnecessary)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6246301f24
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // the source of truth | ||
| if !ok { | ||
| log.Printf("Skipping package %q from Gemfile as it does not exist in the Gemfile.lock\n", gem.name) | ||
| r.Verbosef("Skipping package %q from Gemfile as it does not exist in the Gemfile.lock", gem.name) |
There was a problem hiding this comment.
Default the Gemfile matcher reporter before logging
When GemfileMatcher.Match is invoked directly or via ExtractFromFileWithContext with a zero ScanContext, context.Reporter is nil. For an out-of-sync Gemfile that declares a gem absent from Gemfile.lock (the skip branch this code is handling), this new r.Verbosef call panics instead of returning the remaining packages as the previous log.Printf path did; normalize the reporter with reporter.Effective before logging.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. Applied reporter.Effective(context.Reporter) at both call sites so enrichPackagesWithLocation always receives a non-nil reporter.
| // the source of truth | ||
| if !ok { | ||
| log.Printf("Skipping package %q from gemspec as it does not exist in the Gemfile.lock\n", gem.name) | ||
| r.Verbosef("Skipping package %q from gemspec as it does not exist in the Gemfile.lock", gem.name) |
There was a problem hiding this comment.
Default the gemspec matcher reporter before logging
When GemspecFileMatcher.Match is used by a library caller with a zero ScanContext, r is nil here. A gemspec dependency that is not present in Gemfile.lock now takes this skip path and panics while logging, whereas the previous log.Printf path simply skipped it and preserved the parsed packages; use reporter.Effective or a nil guard before calling Verbosef.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. Applied reporter.Effective(context.Reporter) at the call site so enrichPackagesWithLocation always receives a non-nil reporter.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b78799de2a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return &ReachabilityJava{ | ||
| tsParser: tsParser, | ||
| tsQueriesPerSymbolType: tsQueriesPerSymbolType, | ||
| reporter: r, |
There was a problem hiding this comment.
Default the Java detector reporter
When NewJavaReachableDetector is called with a nil reporter (for example, a library caller preserving the old no-output behavior) and Detect receives an advisory whose symbol Type is not in symbolTypeToTSQuery, the new r.reporter.Warnf path dereferences nil and panics instead of skipping the unsupported symbol as the previous log.Printf did. Store reporter.Effective(r) here so nil remains a silent reporter.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed. Applied reporter.Effective(r) in NewJavaReachableDetector so a nil reporter is silently replaced with VoidReporter rather than panicking on first use.
Summary
log.Printf/log.Printlncalls inpkg/with the existingreporter.Reporterinterface methods (Warnf,Infof,Errorf,Verbosef)Reporterthrough to scanner, extractor matchers (Ruby, Python, JavaScript), and reachability layers where it wasn't previously availableVoidReporterto fully silence all log output, eliminating noise in their service's logsMotivation
Downstream consumers using this library (e.g.
sci) were seeinglog.Printfoutput from the library appearing as noise in their service logs. The library already had the right abstraction (reporter.Reporter+VoidReporter) but 11 call sites bypassed it.Changes
pkg/scanner/datadog_sbom_generator.go— use Reporter already in scopepkg/scanner/vulnerability_result.go— add Reporter parameter toexportMetadatapkg/extractor/ruby/match-gemspec.go,match-gemfile.go— thread Reporter through enrichment functionspkg/extractor/python/pyproject_package_collector.go— addreporterfield to structpkg/extractor/javascript/match-package-json.go— addreporterfield topackageJSONDependencyMappkg/reachability/codefile/java.go— addreporterfield toReachabilityJava, updateNewJavaReachableDetectorsignatureTest plan
log.Print*calls remain inpkg/source files🤖 Generated with Claude Code