Use the slog package and provide command-line argument to control log level

This commit is contained in:
Michael Hohn
2024-08-19 16:02:17 -07:00
committed by =Michael Hohn
parent c9dbba5014
commit e5016b2c9b
3 changed files with 74 additions and 27 deletions

View File

@@ -270,10 +270,16 @@
# Type 'help' for list of commands. # Type 'help' for list of commands.
# (dlv) c # (dlv) c
# dlv debug builds, so the above build may be redundant
dlv debug -- download --session mirva-session-$SN \ dlv debug -- download --session mirva-session-$SN \
--download-dbs \ --download-dbs \
--output-dir mirva-session-$SN-sarif \ --output-dir mirva-session-$SN-sarif
# dlv may say 'no sources', but this works anyay
b main.main
l
# This inline use of dlv may fail; attaching to a process is more reliable
#+END_SRC #+END_SRC
** VS Code Debugger Configuration ** VS Code Debugger Configuration
*** launch.json for download *** launch.json for download

90
main.go
View File

@@ -28,9 +28,12 @@ import (
"compress/gzip" "compress/gzip"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"flag"
"io" "io"
"log" "log"
"log/slog"
"net/http" "net/http"
"os"
"time" "time"
"github.com/GitHubSecurityLab/gh-mrva/cmd" "github.com/GitHubSecurityLab/gh-mrva/cmd"
@@ -40,6 +43,42 @@ import (
) )
func main() { func main() {
helpFlag := flag.Bool("help", false, "Display help message")
logLevel := flag.String("loglevel", "info", "Set log level: debug, info, warn, error")
// Custom usage function for the help flag
flag.Usage = func() {
log.Printf("Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
log.Println("\nExamples:")
log.Println("go run main.go -loglevel=debug ")
}
// Parse the flags
flag.Parse()
// Handle the help flag
if *helpFlag {
flag.Usage()
return
}
// Apply 'loglevel' flag
switch *logLevel {
case "debug":
slog.SetLogLoggerLevel(slog.LevelDebug)
case "info":
slog.SetLogLoggerLevel(slog.LevelInfo)
case "warn":
slog.SetLogLoggerLevel(slog.LevelWarn)
case "error":
slog.SetLogLoggerLevel(slog.LevelError)
default:
log.Printf("Invalid logging verbosity level: %s", *logLevel)
os.Exit(1)
}
var transport = &loghttp.Transport{ var transport = &loghttp.Transport{
Transport: http.DefaultTransport, Transport: http.DefaultTransport,
LogRequest: LogRequestDump, LogRequest: LogRequestDump,
@@ -78,7 +117,7 @@ func IsBase64Gzip(val []byte) bool {
} }
func LogRequestDump(req *http.Request) { func LogRequestDump(req *http.Request) {
log.Printf(">> %s %s", req.Method, req.URL) slog.Debug(">> %s %s", req.Method, req.URL)
req.Body = LogBody(req.Body, "request") req.Body = LogBody(req.Body, "request")
} }
@@ -129,7 +168,7 @@ func LogBody(body io.ReadCloser, from string) io.ReadCloser {
buf, err := io.ReadAll(body) buf, err := io.ReadAll(body)
if err != nil { if err != nil {
var w http.ResponseWriter var w http.ResponseWriter
log.Fatalf("Error reading %s body: %v", from, err.Error()) slog.Error("Error reading %s body: %v", from, err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return nil return nil
} }
@@ -144,36 +183,36 @@ func LogBody(body io.ReadCloser, from string) io.ReadCloser {
// Unknown message, try pretty-printing json // Unknown message, try pretty-printing json
pjson, err := PPJson(string(buf)) pjson, err := PPJson(string(buf))
if err != nil { if err != nil {
log.Printf(">> %s body: %v", from, string(buf)) slog.Debug(">> %s body: %v", from, string(buf))
} else { } else {
log.Printf(">> %s body: {\n%v\n}", from, pjson) slog.Debug(">> %s body: {\n%v\n}", from, pjson)
} }
goto BodyDone goto BodyDone
} }
// Print index for encoded query packs in the json <value>: // Print index for encoded query packs in the json <value>:
// {..."query_pack": <value>,...} // {..."query_pack": <value>,...}
log.Printf(">> %s body: {\n", from) slog.Debug(">> body: {\n", "from", from)
log.Printf(" \"%s\": \"%s\"\n", "action_repo_ref", m.ActionRepoRef) slog.Debug(" \n", "action_repo_ref", m.ActionRepoRef)
log.Printf(" \"%s\": \"%s\"\n", "language", m.Language) slog.Debug(" \n", "language", m.Language)
pjson, err := json.MarshalIndent(m.Repositories, "", " ") pjson, err := json.MarshalIndent(m.Repositories, "", " ")
if err != nil { if err != nil {
log.Printf(" \"%s\": \"%s\"\n", "repositories", m.Repositories[:]) slog.Debug(" \n", "repositories", m.Repositories[:])
} else { } else {
log.Printf(" \"%s\": %s\n", "repositories", pjson) slog.Debug(" \n", "repositories", pjson)
} }
// Provide custom logging for encoded, compressed tar file // Provide custom logging for encoded, compressed tar file
if IsBase64Gzip([]byte(m.QueryPack)) { if IsBase64Gzip([]byte(m.QueryPack)) {
LogBase64GzippedTar(m) LogBase64GzippedTar(m)
} else { } else {
log.Printf(" \"%s\": \"%s\"\n", "query_pack", m.QueryPack) slog.Debug(" \"%s\": \"%s\"\n", "query_pack", m.QueryPack)
} }
log.Printf("\n}") slog.Debug("\n}")
} else { } else {
log.Printf(">> %s body: %v", from, string(buf)) slog.Debug(">> %s body: %v", from, string(buf))
} }
BodyDone: BodyDone:
@@ -201,17 +240,17 @@ func LogBase64GzippedTar(m SubmitMsg) {
// base64 decode the body // base64 decode the body
data, err := base64.StdEncoding.DecodeString(m.QueryPack) data, err := base64.StdEncoding.DecodeString(m.QueryPack)
if err != nil { if err != nil {
log.Fatalln("body decoding error:", err) slog.Error("body decoding error", "err", err)
} }
// gunzip the decoded body // gunzip the decoded body
gzb := bytes.NewBuffer(data) gzb := bytes.NewBuffer(data)
gzr, err := gzip.NewReader(gzb) gzr, err := gzip.NewReader(gzb)
if err != nil { if err != nil {
log.Fatal(err) slog.Error("unzip error", "err", err)
} }
// tar t the gunzipped body // tar t the gunzipped body
log.Printf(" \"%s\": \n", "query_pack") slog.Debug(" \"query_pack\": \n")
log.Printf(" base64 encoded gzipped tar file, contents:\n") slog.Debug(" base64 encoded gzipped tar file, contents:\n")
tr := tar.NewReader(gzr) tr := tar.NewReader(gzr)
for { for {
hdr, err := tr.Next() hdr, err := tr.Next()
@@ -219,10 +258,10 @@ func LogBase64GzippedTar(m SubmitMsg) {
break // End of archive break // End of archive
} }
if err != nil { if err != nil {
log.Fatalln("Tar listing failure:", err) slog.Error("Tar listing failure", "err", err)
} }
// TODO: head / tail the listing // TODO: cli option to head / tail the listing
log.Printf(" %s\n", hdr.Name) slog.Debug(" ", "", hdr.Name)
} }
} }
@@ -236,11 +275,11 @@ func ShowZipIndex(buf []byte, from string) {
} }
// Print the archive index // Print the archive index
log.Printf(">> %s body:\n", from) slog.Debug(">> body:\n", "from", from)
log.Printf("zip file, contents:\n") slog.Debug("zip file, contents:\n")
for _, f := range r.File { for _, f := range r.File {
log.Printf("\t%s\n", f.Name) slog.Debug("\t", f.Name)
} }
} }
@@ -253,10 +292,11 @@ var ContextKeyRequestStart = &contextKey{"RequestStart"}
func LogResponseDump(resp *http.Response) { func LogResponseDump(resp *http.Response) {
ctx := resp.Request.Context() ctx := resp.Request.Context()
if start, ok := ctx.Value(ContextKeyRequestStart).(time.Time); ok { if start, ok := ctx.Value(ContextKeyRequestStart).(time.Time); ok {
log.Printf("<< %d %s (%s)", resp.StatusCode, resp.Request.URL, slog.Debug("<< ", "status", resp.StatusCode,
roundtime.Duration(time.Since(start), 2)) "url", resp.Request.URL,
"duration", roundtime.Duration(time.Since(start), 2))
} else { } else {
log.Printf("<< %d %s", resp.StatusCode, resp.Request.URL) slog.Debug("<< ", "status", resp.StatusCode, "url", resp.Request.URL)
} }
resp.Body = LogBody(resp.Body, "response") resp.Body = LogBody(resp.Body, "response")

View File

@@ -9,6 +9,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"log/slog"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@@ -591,7 +592,7 @@ func downloadArtifact(url string, task models.DownloadTask) error {
if len(downloadedFiles) == 0 { if len(downloadedFiles) == 0 {
return errors.New("No results files found in artifact") return errors.New("No results files found in artifact")
} else { } else {
fmt.Println("Downloaded", downloadedFiles) slog.Info("Downloaded", downloadedFiles)
return nil return nil
} }
} }