@@ -3,7 +3,7 @@ package diagnostics
33import (
44 "encoding/json"
55 "fmt"
6- "log"
6+ "log/slog "
77 "os"
88 "strings"
99 "time"
@@ -56,18 +56,65 @@ type diagnostic struct {
5656var diagnosticsEmitted , diagnosticsLimit uint = 0 , 100
5757var noDiagnosticDirPrinted bool = false
5858
59- func emitDiagnostic ( sourceid , sourcename , markdownMessage string , severity diagnosticSeverity , visibility * visibilityStruct , location * locationStruct ) {
60- if diagnosticsEmitted < diagnosticsLimit {
61- diagnosticsEmitted += 1
59+ type DiagnosticsWriter interface {
60+ WriteDiagnostic ( d diagnostic )
61+ }
6262
63- diagnosticDir := os .Getenv ("CODEQL_EXTRACTOR_GO_DIAGNOSTIC_DIR" )
64- if diagnosticDir == "" {
65- if ! noDiagnosticDirPrinted {
66- log .Println ("No diagnostic directory set, so not emitting diagnostic" )
67- noDiagnosticDirPrinted = true
68- }
69- return
63+ type FileDiagnosticsWriter struct {
64+ diagnosticDir string
65+ }
66+
67+ func (writer * FileDiagnosticsWriter ) WriteDiagnostic (d diagnostic ) {
68+ if writer == nil {
69+ return
70+ }
71+
72+ content , err := json .Marshal (d )
73+ if err != nil {
74+ slog .Error ("Failed to encode diagnostic as JSON" , slog .Any ("err" , err ))
75+ return
76+ }
77+
78+ targetFile , err := os .CreateTemp (writer .diagnosticDir , "go-extractor.*.json" )
79+ if err != nil {
80+ slog .Error ("Failed to create diagnostic file" , slog .Any ("err" , err ))
81+ return
82+ }
83+ defer func () {
84+ if err := targetFile .Close (); err != nil {
85+ slog .Error ("Failed to close diagnostic file" , slog .Any ("err" , err ))
86+ }
87+ }()
88+
89+ _ , err = targetFile .Write (content )
90+ if err != nil {
91+ slog .Error ("Failed to write to diagnostic file" , slog .Any ("err" , err ))
92+ }
93+ }
94+
95+ var DefaultWriter * FileDiagnosticsWriter = nil
96+
97+ func NewFileDiagnosticsWriter () * FileDiagnosticsWriter {
98+ diagnosticDir := os .Getenv ("CODEQL_EXTRACTOR_GO_DIAGNOSTIC_DIR" )
99+ if diagnosticDir == "" {
100+ if ! noDiagnosticDirPrinted {
101+ slog .Warn ("No diagnostic directory set, so not emitting diagnostics" )
102+ noDiagnosticDirPrinted = true
70103 }
104+ return nil
105+ }
106+
107+ return & FileDiagnosticsWriter {diagnosticDir }
108+ }
109+
110+ func init () {
111+ DefaultWriter = NewFileDiagnosticsWriter ()
112+ }
113+
114+ // Emits a diagnostic using the specified `DiagnosticsWriter`.
115+ func emitDiagnosticTo (writer DiagnosticsWriter , sourceid , sourcename , markdownMessage string , severity diagnosticSeverity , visibility * visibilityStruct , location * locationStruct ) {
116+ if diagnosticsEmitted < diagnosticsLimit {
117+ diagnosticsEmitted += 1
71118
72119 timestamp := time .Now ().UTC ().Format ("2006-01-02T15:04:05.000" ) + "Z"
73120
@@ -93,33 +140,15 @@ func emitDiagnostic(sourceid, sourcename, markdownMessage string, severity diagn
93140 }
94141 }
95142
96- content , err := json .Marshal (d )
97- if err != nil {
98- log .Println (err )
99- return
100- }
101-
102- targetFile , err := os .CreateTemp (diagnosticDir , "go-extractor.*.json" )
103- if err != nil {
104- log .Println ("Failed to create diagnostic file: " )
105- log .Println (err )
106- return
107- }
108- defer func () {
109- if err := targetFile .Close (); err != nil {
110- log .Println ("Failed to close diagnostic file:" )
111- log .Println (err )
112- }
113- }()
114-
115- _ , err = targetFile .Write (content )
116- if err != nil {
117- log .Println ("Failed to write to diagnostic file: " )
118- log .Println (err )
119- }
143+ writer .WriteDiagnostic (d )
120144 }
121145}
122146
147+ // Emits a diagnostic using the default `DiagnosticsWriter`.
148+ func emitDiagnostic (sourceid , sourcename , markdownMessage string , severity diagnosticSeverity , visibility * visibilityStruct , location * locationStruct ) {
149+ emitDiagnosticTo (DefaultWriter , sourceid , sourcename , markdownMessage , severity , visibility , location )
150+ }
151+
123152func EmitPackageDifferentOSArchitecture (pkgPath string ) {
124153 emitDiagnostic (
125154 "go/autobuilder/package-different-os-architecture" ,
@@ -141,7 +170,7 @@ func plural(n int, singular, plural string) string {
141170
142171const maxNumPkgPaths = 5
143172
144- func EmitCannotFindPackages (pkgPaths []string ) {
173+ func EmitCannotFindPackages (writer DiagnosticsWriter , pkgPaths []string ) {
145174 numPkgPaths := len (pkgPaths )
146175
147176 numPrinted := numPkgPaths
@@ -188,7 +217,8 @@ func EmitCannotFindPackages(pkgPaths []string) {
188217 "If any of the packages are already present in the repository, but were not found, then you may need a [custom build command](https://docs.github.com/en/code-security/how-tos/scan-code-for-vulnerabilities/manage-your-configuration/codeql-code-scanning-for-compiled-languages)."
189218 }
190219
191- emitDiagnostic (
220+ emitDiagnosticTo (
221+ writer ,
192222 "go/autobuilder/package-not-found" ,
193223 "Some packages could not be found" ,
194224 message ,
0 commit comments