package repository import ( "encoding/json" "log/slog" "os" "strings" "time" "github.com/spf13/viper" ) // srrdbAppendJSONL adds one object as a single line to a .jsonl log. A missing // or failing log never changes the outcome of the run itself. func srrdbAppendJSONL(key string, record map[string]any) { path := viper.GetString(key) if path == "" { return } data, err := json.Marshal(record) if err != nil { slog.Error("encode srrdb log record", "key", key, "err", err) return } file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { slog.Error("open srrdb log", "path", path, "err", err) return } defer func() { if cerr := file.Close(); cerr != nil { slog.Error("close srrdb log", "path", path, "err", cerr) } }() if _, err := file.Write(append(data, '\n')); err != nil { slog.Error("write srrdb log", "path", path, "err", err) } } // srrdbLogStatus appends the outcome of one finished run to srrdb.log. func srrdbLogStatus(uri string, stored, reported int) { srrdbAppendJSONL("srrdb.log", map[string]any{ "time": time.Now().Format(srrdbTimestamp), "uri": uri, "stored": stored, "reported": reported, }) } // srrdbLogWarning records warnings reported by the API. They share the failure // file but carry their own kind, because the endpoint answers an unrecognized // keyword with HTTP 200 and an empty result set: the text is the only trace of a // bad path, and it must stay distinguishable from a real breakdown. func srrdbLogWarning(uri string, warnings []string) { srrdbAppendJSONL("srrdb.error_log", map[string]any{ "kind": "warning", "time": time.Now().Format(srrdbTimestamp), "uri": uri, "warnings": strings.Join(warnings, "; "), }) } // srrdbLogError appends one failure to srrdb.error_log. func srrdbLogError(uri string, err error) { srrdbAppendJSONL("srrdb.error_log", map[string]any{ "kind": "error", "time": time.Now().Format(srrdbTimestamp), "uri": uri, "error": err.Error(), }) }