From f396b2f7129c431d7deb714db5dcbd587ec9bc88 Mon Sep 17 00:00:00 2001 From: Mateusz Filipowicz Date: Fri, 7 Feb 2025 17:05:35 +0100 Subject: [PATCH] chore: improve logging and add trace logging with --trace flag --- fields/download.go | 59 +++++++++++++++++++++++++++------------------ fields/generator.go | 2 +- fields/main.go | 38 +++++++++++++++-------------- 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/fields/download.go b/fields/download.go index f60bcd2..cf8449b 100644 --- a/fields/download.go +++ b/fields/download.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + log "github.com/sirupsen/logrus" "io" "net/http" "net/url" @@ -20,24 +21,6 @@ import ( "github.com/xor-gate/ar" ) -func sanitizeExtractedPath(filePath, destinationDir string) (string, error) { - absDestinationDir, err := filepath.Abs(destinationDir) - if err != nil { - return "", err - } - - absFilePath, err := filepath.Abs(filepath.Join(destinationDir, filePath)) - if err != nil { - return "", err - } - - if !strings.HasPrefix(absFilePath, absDestinationDir) { - return "", fmt.Errorf("invalid file path: %s", filePath) - } - - return absFilePath, nil -} - func DownloadAndExtract(downloadUrl url.URL, outputDir string) error { targetInfo, err := os.Stat(outputDir) if err != nil { @@ -51,16 +34,19 @@ func DownloadAndExtract(downloadUrl url.URL, outputDir string) error { } // download fields, create + log.Debugf("downloading UniFi Controller package from: %s", downloadUrl.String()) jarFile, err := downloadJar(downloadUrl, outputDir) if err != nil { return err } + log.Debugf("extracting JSON files with API structures from: %s to: %s", jarFile, outputDir) err = extractJSON(jarFile, outputDir) if err != nil { return err } + log.Debugf("JSON files extracted to: %s", outputDir) targetInfo, err = os.Stat(outputDir) if err != nil { return err @@ -113,6 +99,7 @@ func downloadJar(downloadUrl url.URL, outputDir string) (string, error) { var aceJar *os.File + log.Debugln("extracting ace.jar from downloaded controller package") for { header, err := tarReader.Next() if errors.Is(err, io.EOF) { @@ -142,10 +129,28 @@ func downloadJar(downloadUrl url.URL, outputDir string) (string, error) { } defer aceJar.Close() - + log.Debugf("ace.jar extracted to: %s", aceJar.Name()) return aceJar.Name(), nil } +func sanitizeExtractedPath(filePath, destinationDir string) (string, error) { + absDestinationDir, err := filepath.Abs(destinationDir) + if err != nil { + return "", err + } + + absFilePath, err := filepath.Abs(filepath.Join(destinationDir, filepath.Base(filePath))) + if err != nil { + return "", err + } + + if !strings.HasPrefix(absFilePath, absDestinationDir) { + return "", fmt.Errorf("invalid file path: %s", filePath) + } + + return absFilePath, nil +} + func extractJSON(jarFile, fieldsDir string) error { jarZip, err := zip.OpenReader(jarFile) if err != nil { @@ -153,6 +158,7 @@ func extractJSON(jarFile, fieldsDir string) error { } defer jarZip.Close() + log.Tracef("opened jar %s with %d files", jarFile, len(jarZip.File)) for _, f := range jarZip.File { if !strings.HasPrefix(f.Name, "api/fields/") || path.Ext(f.Name) != ".json" { // skip file @@ -160,11 +166,11 @@ func extractJSON(jarFile, fieldsDir string) error { } err = func() error { + log.Tracef("extracting %s", f.Name) src, err := f.Open() if err != nil { return err } - dstPath, err := sanitizeExtractedPath(f.Name, fieldsDir) if err != nil { return err @@ -177,6 +183,7 @@ func extractJSON(jarFile, fieldsDir string) error { defer dst.Close() _, err = io.Copy(dst, src) + log.Debugf("extracted %s", f.Name) if err != nil { return err } @@ -202,18 +209,22 @@ func extractJSON(jarFile, fieldsDir string) error { return fmt.Errorf("unable to unmarshal settings: %w", err) } - for k, v := range settings { - fileName := fmt.Sprintf("Setting%s.json", strcase.ToCamel(k)) + log.Debugf("splitting Settings.json into individual setting files") + for settingKey, settingValue := range settings { + settingName := strcase.ToCamel(settingKey) + fileName := fmt.Sprintf("Setting%s.json", settingName) + log.Tracef("splitting %s", fileName) - data, err := json.MarshalIndent(v, "", " ") + data, err := json.MarshalIndent(settingValue, "", " ") if err != nil { - return fmt.Errorf("unable to marshal setting %q: %w", k, err) + return fmt.Errorf("unable to marshal setting %q: %w", settingKey, err) } err = os.WriteFile(filepath.Join(fieldsDir, fileName), data, 0o755) if err != nil { return fmt.Errorf("unable to write new settings file: %w", err) } + log.Tracef("splitted %s into %s", settingKey, fileName) } // TODO: cleanup JSON diff --git a/fields/generator.go b/fields/generator.go index c20c96c..d7a0176 100644 --- a/fields/generator.go +++ b/fields/generator.go @@ -278,7 +278,7 @@ func (r *Resource) fieldInfoFromValidation(name string, validation interface{}) } } if validation != "" && normalized != "" { - log.Debugf("normalize %q to %q", validation, normalized) + log.Tracef("normalize %q to %q", validation, normalized) } omitEmpty = omitEmpty || (!strings.Contains(validation, "^$") && !strings.HasSuffix(fieldName, "ID")) diff --git a/fields/main.go b/fields/main.go index ea57d21..9add694 100644 --- a/fields/main.go +++ b/fields/main.go @@ -18,13 +18,15 @@ func usage() { flag.PrintDefaults() } -func setupLogging(debugEnabled bool) { +func setupLogging(debugEnabled, traceEnabled bool) { log.SetFormatter(&log.TextFormatter{ DisableTimestamp: true, DisableLevelTruncation: true, FullTimestamp: false, }) - if debugEnabled { + if traceEnabled { + log.SetLevel(log.TraceLevel) + } else if debugEnabled { log.SetLevel(log.DebugLevel) } else { log.SetLevel(log.InfoLevel) @@ -36,18 +38,19 @@ func main() { versionBaseDirFlag := flag.String("version-base-dir", ".", "The base directory for version JSON files") outputDirFlag := flag.String("output-dir", ".", "The output directory of the generated Go code") - downloadOnly := flag.Bool("download-only", false, "Only download and build the fields JSON directory, do not generate") + downloadOnly := flag.Bool("download-only", false, "Only download and build the API structures JSON directory, do not generate") debugFlag := flag.Bool("debug", false, "Enable debug logging") + traceFlag := flag.Bool("trace", false, "Enable trace logging") flag.Parse() - setupLogging(*debugFlag) + setupLogging(*debugFlag, *traceFlag) specifiedVersion := strings.TrimSpace(flag.Arg(0)) if specifiedVersion == "" { specifiedVersion = LatestVersionMarker // default to latest version } unifiVersion, err := determineUnifiVersion(specifiedVersion) if err != nil { - log.Fatalf("unable to determine version and download URL for Unifi version %s", specifiedVersion) + log.Fatalf("unable to determine version and download URL for Unifi version %s: %s", specifiedVersion, err) panic(err) } @@ -56,41 +59,40 @@ func main() { wd, err := os.Getwd() if err != nil { - log.Fatalln("unable to determine working directory") + log.Fatalf("unable to determine working directory: %s", err) panic(err) } - fieldsDir := filepath.Join(wd, *versionBaseDirFlag, fmt.Sprintf("v%s", unifiVersion.Version)) - log.Infoln("Downloading UniFi Controller field definitions...") - err = DownloadAndExtract(*unifiVersion.DownloadUrl, fieldsDir) + structuresDir := filepath.Join(wd, *versionBaseDirFlag, fmt.Sprintf("v%s", unifiVersion.Version)) + log.Infoln("Downloading UniFi Controller API structures definitions...") + err = DownloadAndExtract(*unifiVersion.DownloadUrl, structuresDir) if err != nil { - log.Fatalf("unable to download and extract UniFi Controller field definitions: %s", err) + log.Fatalf("unable to download and extract UniFi Controller API structures definitions: %s", err) panic(err) } - log.Infof("Downloaded UniFi Controller field definitions in %s", fieldsDir) + log.Infof("Downloaded UniFi Controller API structures definitions in %s", structuresDir) if *downloadOnly { - log.Infoln("Fields JSON ready!") + log.Infoln("Structure JSONs ready!") os.Exit(0) } log.Infoln("Generating resources code...") outDir := filepath.Join(wd, *outputDirFlag) - if err = generateCode(fieldsDir, outDir); err != nil { - log.Fatalln("unable to generate resources code") + if err = generateCode(structuresDir, outDir); err != nil { + log.Fatalf("unable to generate resources code: %s", err) panic(err) } log.Infof("Writing version file...") if err = writeVersionFile(unifiVersion.Version, outDir); err != nil { - log.Fatalf("failed to write version file to %s", outDir) + log.Fatalf("failed to write version file to %s: %s", outDir, err) panic(err) } - workingDir, _ := os.Getwd() - basepath := filepath.Dir(workingDir) + basepath := filepath.Dir(wd) if err = writeVersionRepoMarkerFile(unifiVersion.Version, basepath); err != nil { - log.Fatalf("failed to write version file to %s", basepath) + log.Fatalf("failed to write version file to %s: %s", basepath, err) panic(err) }