switch to the standard logger

This commit is contained in:
Nazar Kanaev 2021-03-16 12:54:53 +00:00
parent 3539433a9d
commit cc7bdc5b76
11 changed files with 75 additions and 71 deletions

View File

@ -6,7 +6,6 @@
- fix: scrollTo/scrollBy with smooth behavior instead of scrollTop - fix: scrollTo/scrollBy with smooth behavior instead of scrollTop
- ref: switch to the standard logger
- ref: organize "server" package using KonMari method - ref: organize "server" package using KonMari method
https://github.com/gin-gonic/gin : nice example of router api https://github.com/gin-gonic/gin : nice example of router api

View File

@ -18,6 +18,9 @@ var Version string = "0.0"
var GitHash string = "unknown" var GitHash string = "unknown"
func main() { func main() {
log.SetOutput(os.Stdout)
log.SetFlags(log.Ldate|log.Ltime|log.Lshortfile)
var addr, db, authfile, certfile, keyfile string var addr, db, authfile, certfile, keyfile string
var ver, open bool var ver, open bool
flag.StringVar(&addr, "addr", "127.0.0.1:7070", "address to run server on") flag.StringVar(&addr, "addr", "127.0.0.1:7070", "address to run server on")
@ -43,28 +46,26 @@ func main() {
server.BasePath = strings.TrimSuffix(server.BasePath, "/") server.BasePath = strings.TrimSuffix(server.BasePath, "/")
} }
logger := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)
configPath, err := os.UserConfigDir() configPath, err := os.UserConfigDir()
if err != nil { if err != nil {
logger.Fatal("Failed to get config dir: ", err) log.Fatal("Failed to get config dir: ", err)
} }
if db == "" { if db == "" {
storagePath := filepath.Join(configPath, "yarr") storagePath := filepath.Join(configPath, "yarr")
if err := os.MkdirAll(storagePath, 0755); err != nil { if err := os.MkdirAll(storagePath, 0755); err != nil {
logger.Fatal("Failed to create app config dir: ", err) log.Fatal("Failed to create app config dir: ", err)
} }
db = filepath.Join(storagePath, "storage.db") db = filepath.Join(storagePath, "storage.db")
} }
logger.Printf("using db file %s", db) log.Printf("using db file %s", db)
var username, password string var username, password string
if authfile != "" { if authfile != "" {
f, err := os.Open(authfile) f, err := os.Open(authfile)
if err != nil { if err != nil {
logger.Fatal("Failed to open auth file: ", err) log.Fatal("Failed to open auth file: ", err)
} }
defer f.Close() defer f.Close()
scanner := bufio.NewScanner(f) scanner := bufio.NewScanner(f)
@ -72,7 +73,7 @@ func main() {
line := scanner.Text() line := scanner.Text()
parts := strings.Split(line, ":") parts := strings.Split(line, ":")
if len(parts) != 2 { if len(parts) != 2 {
logger.Fatalf("Invalid auth: %v (expected `username:password`)", line) log.Fatalf("Invalid auth: %v (expected `username:password`)", line)
} }
username = parts[0] username = parts[0]
password = parts[1] password = parts[1]
@ -81,15 +82,15 @@ func main() {
} }
if (certfile != "" || keyfile != "") && (certfile == "" || keyfile == "") { if (certfile != "" || keyfile != "") && (certfile == "" || keyfile == "") {
logger.Fatalf("Both cert & key files are required") log.Fatalf("Both cert & key files are required")
} }
store, err := storage.New(db, logger) store, err := storage.New(db)
if err != nil { if err != nil {
logger.Fatal("Failed to initialise database: ", err) log.Fatal("Failed to initialise database: ", err)
} }
srv := server.New(store, logger, addr) srv := server.New(store, addr)
if certfile != "" && keyfile != "" { if certfile != "" && keyfile != "" {
srv.CertFile = certfile srv.CertFile = certfile
@ -101,7 +102,7 @@ func main() {
srv.Password = password srv.Password = password
} }
logger.Printf("starting server at %s", srv.GetAddr()) log.Printf("starting server at %s", srv.GetAddr())
if open { if open {
platform.Open(srv.GetAddr()) platform.Open(srv.GetAddr())
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/nkanaev/yarr/src/assets" "github.com/nkanaev/yarr/src/assets"
"html" "html"
"io/ioutil" "io/ioutil"
"log"
"math" "math"
"net/http" "net/http"
"reflect" "reflect"
@ -94,7 +95,7 @@ func FolderListHandler(rw http.ResponseWriter, req *http.Request) {
} else if req.Method == "POST" { } else if req.Method == "POST" {
var body FolderCreateForm var body FolderCreateForm
if err := json.NewDecoder(req.Body).Decode(&body); err != nil { if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
handler(req).log.Print(err) log.Print(err)
rw.WriteHeader(http.StatusBadRequest) rw.WriteHeader(http.StatusBadRequest)
return return
} }
@ -120,7 +121,7 @@ func FolderHandler(rw http.ResponseWriter, req *http.Request) {
if req.Method == "PUT" { if req.Method == "PUT" {
var body FolderUpdateForm var body FolderUpdateForm
if err := json.NewDecoder(req.Body).Decode(&body); err != nil { if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
handler(req).log.Print(err) log.Print(err)
rw.WriteHeader(http.StatusBadRequest) rw.WriteHeader(http.StatusBadRequest)
return return
} }
@ -174,14 +175,14 @@ func FeedListHandler(rw http.ResponseWriter, req *http.Request) {
} else if req.Method == "POST" { } else if req.Method == "POST" {
var form FeedCreateForm var form FeedCreateForm
if err := json.NewDecoder(req.Body).Decode(&form); err != nil { if err := json.NewDecoder(req.Body).Decode(&form); err != nil {
handler(req).log.Print(err) log.Print(err)
rw.WriteHeader(http.StatusBadRequest) rw.WriteHeader(http.StatusBadRequest)
return return
} }
feed, sources, err := discoverFeed(form.Url) feed, sources, err := discoverFeed(form.Url)
if err != nil { if err != nil {
handler(req).log.Print(err) log.Print(err)
writeJSON(rw, map[string]string{"status": "notfound"}) writeJSON(rw, map[string]string{"status": "notfound"})
return return
} }
@ -201,7 +202,7 @@ func FeedListHandler(rw http.ResponseWriter, req *http.Request) {
db(req).UpdateFeedIcon(storedFeed.Id, icon) db(req).UpdateFeedIcon(storedFeed.Id, icon)
} }
if err != nil { if err != nil {
handler(req).log.Printf("Failed to find favicon for %s (%d): %s", storedFeed.FeedLink, storedFeed.Id, err) log.Printf("Failed to find favicon for %s (%d): %s", storedFeed.FeedLink, storedFeed.Id, err)
} }
writeJSON(rw, map[string]string{"status": "success"}) writeJSON(rw, map[string]string{"status": "success"})
@ -227,7 +228,7 @@ func FeedHandler(rw http.ResponseWriter, req *http.Request) {
} }
body := make(map[string]interface{}) body := make(map[string]interface{})
if err := json.NewDecoder(req.Body).Decode(&body); err != nil { if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
handler(req).log.Print(err) log.Print(err)
rw.WriteHeader(http.StatusBadRequest) rw.WriteHeader(http.StatusBadRequest)
return return
} }
@ -262,7 +263,7 @@ func ItemHandler(rw http.ResponseWriter, req *http.Request) {
} }
var body ItemUpdateForm var body ItemUpdateForm
if err := json.NewDecoder(req.Body).Decode(&body); err != nil { if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
handler(req).log.Print(err) log.Print(err)
rw.WriteHeader(http.StatusBadRequest) rw.WriteHeader(http.StatusBadRequest)
return return
} }
@ -347,12 +348,12 @@ func OPMLImportHandler(rw http.ResponseWriter, req *http.Request) {
if req.Method == "POST" { if req.Method == "POST" {
file, _, err := req.FormFile("opml") file, _, err := req.FormFile("opml")
if err != nil { if err != nil {
handler(req).log.Print(err) log.Print(err)
return return
} }
doc, err := parseOPML(file) doc, err := parseOPML(file)
if err != nil { if err != nil {
handler(req).log.Print(err) log.Print(err)
return return
} }
for _, outline := range doc.Outlines { for _, outline := range doc.Outlines {

View File

@ -15,7 +15,6 @@ import (
type Handler struct { type Handler struct {
Addr string Addr string
db *storage.Storage db *storage.Storage
log *log.Logger
feedQueue chan storage.Feed feedQueue chan storage.Feed
queueSize *int32 queueSize *int32
refreshRate chan int64 refreshRate chan int64
@ -27,11 +26,10 @@ type Handler struct {
KeyFile string KeyFile string
} }
func New(db *storage.Storage, logger *log.Logger, addr string) *Handler { func New(db *storage.Storage, addr string) *Handler {
queueSize := int32(0) queueSize := int32(0)
return &Handler{ return &Handler{
db: db, db: db,
log: logger,
feedQueue: make(chan storage.Feed, 3000), feedQueue: make(chan storage.Feed, 3000),
queueSize: &queueSize, queueSize: &queueSize,
Addr: addr, Addr: addr,
@ -58,7 +56,7 @@ func (h *Handler) Start() {
err = s.ListenAndServe() err = s.ListenAndServe()
} }
if err != http.ErrServerClosed { if err != http.ErrServerClosed {
h.log.Fatal(err) log.Fatal(err)
} }
} }
@ -124,7 +122,7 @@ func (h *Handler) startJobs() {
items, err := listItems(feed, h.db) items, err := listItems(feed, h.db)
atomic.AddInt32(h.queueSize, -1) atomic.AddInt32(h.queueSize, -1)
if err != nil { if err != nil {
h.log.Printf("Failed to fetch %s (%d): %s", feed.FeedLink, feed.Id, err) log.Printf("Failed to fetch %s (%d): %s", feed.FeedLink, feed.Id, err)
h.db.SetFeedError(feed.Id, err) h.db.SetFeedError(feed.Id, err)
continue continue
} }
@ -136,7 +134,7 @@ func (h *Handler) startJobs() {
h.db.UpdateFeedIcon(feed.Id, icon) h.db.UpdateFeedIcon(feed.Id, icon)
} }
if err != nil { if err != nil {
h.log.Printf("Failed to search favicon for %s (%s): %s", feed.Link, feed.FeedLink, err) log.Printf("Failed to search favicon for %s (%s): %s", feed.Link, feed.FeedLink, err)
} }
} }
case <-delTicker.C: case <-delTicker.C:
@ -190,7 +188,7 @@ func (h Handler) requiresAuth() bool {
} }
func (h *Handler) fetchAllFeeds() { func (h *Handler) fetchAllFeeds() {
h.log.Print("Refreshing all feeds") log.Print("Refreshing all feeds")
h.db.ResetFeedErrors() h.db.ResetFeedErrors()
for _, feed := range h.db.ListFeeds() { for _, feed := range h.db.ListFeeds() {
h.fetchFeed(feed) h.fetchFeed(feed)

View File

@ -1,6 +1,7 @@
package storage package storage
import ( import (
"log"
"html" "html"
"net/url" "net/url"
) )
@ -60,7 +61,7 @@ func (s *Storage) CreateFeed(title, description, link, feedLink string, folderId
func (s *Storage) DeleteFeed(feedId int64) bool { func (s *Storage) DeleteFeed(feedId int64) bool {
_, err := s.db.Exec(`delete from feeds where id = ?`, feedId) _, err := s.db.Exec(`delete from feeds where id = ?`, feedId)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
} }
return err == nil return err == nil
} }
@ -89,7 +90,7 @@ func (s *Storage) ListFeeds() []Feed {
order by title collate nocase order by title collate nocase
`) `)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
for rows.Next() { for rows.Next() {
@ -104,7 +105,7 @@ func (s *Storage) ListFeeds() []Feed {
&f.HasIcon, &f.HasIcon,
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
result = append(result, f) result = append(result, f)
@ -137,7 +138,7 @@ func (s *Storage) GetFeed(id int64) *Feed {
func (s *Storage) ResetFeedErrors() { func (s *Storage) ResetFeedErrors() {
if _, err := s.db.Exec(`delete from feed_errors`); err != nil { if _, err := s.db.Exec(`delete from feed_errors`); err != nil {
s.log.Print(err) log.Print(err)
} }
} }
@ -149,7 +150,7 @@ func (s *Storage) SetFeedError(feedID int64, lastError error) {
feedID, lastError.Error(), feedID, lastError.Error(),
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
} }
} }
@ -158,7 +159,7 @@ func (s *Storage) GetFeedErrors() map[int64]string {
rows, err := s.db.Query(`select feed_id, error from feed_errors`) rows, err := s.db.Query(`select feed_id, error from feed_errors`)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return errors return errors
} }
@ -166,7 +167,7 @@ func (s *Storage) GetFeedErrors() map[int64]string {
var id int64 var id int64
var error string var error string
if err = rows.Scan(&id, &error); err != nil { if err = rows.Scan(&id, &error); err != nil {
s.log.Print(err) log.Print(err)
} }
errors[id] = error errors[id] = error
} }

View File

@ -2,6 +2,7 @@ package storage
import ( import (
"fmt" "fmt"
"log"
) )
type Folder struct { type Folder struct {
@ -25,19 +26,19 @@ func (s *Storage) CreateFolder(title string) *Folder {
var id int64 var id int64
numrows, err := result.RowsAffected() numrows, err := result.RowsAffected()
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return nil return nil
} }
if numrows == 1 { if numrows == 1 {
id, err = result.LastInsertId() id, err = result.LastInsertId()
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return nil return nil
} }
} else { } else {
err = s.db.QueryRow(`select id, is_expanded from folders where title=?`, title).Scan(&id, &expanded) err = s.db.QueryRow(`select id, is_expanded from folders where title=?`, title).Scan(&id, &expanded)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return nil return nil
} }
} }
@ -47,7 +48,7 @@ func (s *Storage) CreateFolder(title string) *Folder {
func (s *Storage) DeleteFolder(folderId int64) bool { func (s *Storage) DeleteFolder(folderId int64) bool {
_, err := s.db.Exec(`delete from folders where id = ?`, folderId) _, err := s.db.Exec(`delete from folders where id = ?`, folderId)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
} }
return err == nil return err == nil
} }
@ -70,14 +71,14 @@ func (s *Storage) ListFolders() []Folder {
order by title collate nocase order by title collate nocase
`) `)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
for rows.Next() { for rows.Next() {
var f Folder var f Folder
err = rows.Scan(&f.Id, &f.Title, &f.IsExpanded) err = rows.Scan(&f.Id, &f.Title, &f.IsExpanded)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
result = append(result, f) result = append(result, f)

View File

@ -1,6 +1,7 @@
package storage package storage
import ( import (
"log"
"time" "time"
) )
@ -16,7 +17,7 @@ func (s *Storage) ListHTTPStates() map[int64]HTTPState {
result := make(map[int64]HTTPState) result := make(map[int64]HTTPState)
rows, err := s.db.Query(`select feed_id, last_refreshed, last_modified, etag from http_states`) rows, err := s.db.Query(`select feed_id, last_refreshed, last_modified, etag from http_states`)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
for rows.Next() { for rows.Next() {
@ -28,7 +29,7 @@ func (s *Storage) ListHTTPStates() map[int64]HTTPState {
&state.Etag, &state.Etag,
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
result[state.FeedID] = state result[state.FeedID] = state
@ -67,6 +68,6 @@ func (s *Storage) SetHTTPState(feedID int64, lastModified, etag string) {
lastModified, etag, lastModified, etag,
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
} }
} }

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"html" "html"
"log"
"strings" "strings"
"time" "time"
xhtml "golang.org/x/net/html" xhtml "golang.org/x/net/html"
@ -73,7 +74,7 @@ type MarkFilter struct {
func (s *Storage) CreateItems(items []Item) bool { func (s *Storage) CreateItems(items []Item) bool {
tx, err := s.db.Begin() tx, err := s.db.Begin()
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return false return false
} }
now := time.Now() now := time.Now()
@ -105,16 +106,16 @@ func (s *Storage) CreateItems(items []Item) bool {
item.DateUpdated, now, item.DateUpdated, now,
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
if err = tx.Rollback(); err != nil { if err = tx.Rollback(); err != nil {
s.log.Print(err) log.Print(err)
return false return false
} }
return false return false
} }
} }
if err = tx.Commit(); err != nil { if err = tx.Commit(); err != nil {
s.log.Print(err) log.Print(err)
return false return false
} }
return true return true
@ -175,7 +176,7 @@ func (s *Storage) ListItems(filter ItemFilter, offset, limit int, newestFirst bo
`, predicate, order, limit, offset) `, predicate, order, limit, offset)
rows, err := s.db.Query(query, args...) rows, err := s.db.Query(query, args...)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
for rows.Next() { for rows.Next() {
@ -196,7 +197,7 @@ func (s *Storage) ListItems(filter ItemFilter, offset, limit int, newestFirst bo
&x.PodcastURL, &x.PodcastURL,
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
result = append(result, x) result = append(result, x)
@ -251,7 +252,7 @@ func (s *Storage) MarkItemsRead(filter MarkFilter) bool {
`, READ, predicate, STARRED) `, READ, predicate, STARRED)
_, err := s.db.Exec(query, args...) _, err := s.db.Exec(query, args...)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
} }
return err == nil return err == nil
} }
@ -273,7 +274,7 @@ func (s *Storage) FeedStats() []FeedStat {
group by feed_id group by feed_id
`, UNREAD, STARRED)) `, UNREAD, STARRED))
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
for rows.Next() { for rows.Next() {
@ -310,7 +311,7 @@ func (s *Storage) SyncSearch() {
where search_rowid is null; where search_rowid is null;
`) `)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return return
} }
@ -327,7 +328,7 @@ func (s *Storage) SyncSearch() {
item.Title, HTMLText(item.Description), HTMLText(item.Content), item.Title, HTMLText(item.Description), HTMLText(item.Content),
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return return
} }
if numrows, err := result.RowsAffected(); err == nil && numrows == 1 { if numrows, err := result.RowsAffected(); err == nil && numrows == 1 {
@ -351,7 +352,7 @@ func (s *Storage) DeleteOldItems() {
`, STARRED)) `, STARRED))
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return return
} }
@ -370,16 +371,16 @@ func (s *Storage) DeleteOldItems() {
time.Now().Add(-time.Hour*24*90), // 90 days time.Now().Add(-time.Hour*24*90), // 90 days
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return return
} }
num, err := result.RowsAffected() num, err := result.RowsAffected()
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return return
} }
if num > 0 { if num > 0 {
s.log.Printf("Deleted %d old items (%d)", num, feedId) log.Printf("Deleted %d old items (%d)", num, feedId)
} }
} }
} }

View File

@ -15,7 +15,7 @@ var migrations = []func(*sql.Tx)error{
var maxVersion = int64(len(migrations)) var maxVersion = int64(len(migrations))
func migrate(db *sql.DB, log *log.Logger) error { func migrate(db *sql.DB) error {
var version int64 var version int64
db.QueryRow("pragma user_version").Scan(&version); db.QueryRow("pragma user_version").Scan(&version);

View File

@ -1,6 +1,9 @@
package storage package storage
import "encoding/json" import (
"encoding/json"
"log"
)
func settingsDefaults() map[string]interface{} { func settingsDefaults() map[string]interface{} {
return map[string]interface{}{ return map[string]interface{}{
@ -28,7 +31,7 @@ func (s *Storage) GetSettingsValue(key string) interface{} {
} }
var valDecoded interface{} var valDecoded interface{}
if err := json.Unmarshal([]byte(val), &valDecoded); err != nil { if err := json.Unmarshal([]byte(val), &valDecoded); err != nil {
s.log.Print(err) log.Print(err)
return nil return nil
} }
return valDecoded return valDecoded
@ -48,7 +51,7 @@ func (s *Storage) GetSettings() map[string]interface{} {
result := settingsDefaults() result := settingsDefaults()
rows, err := s.db.Query(`select key, val from settings;`) rows, err := s.db.Query(`select key, val from settings;`)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return result return result
} }
for rows.Next() { for rows.Next() {
@ -58,7 +61,7 @@ func (s *Storage) GetSettings() map[string]interface{} {
rows.Scan(&key, &val) rows.Scan(&key, &val)
if err = json.Unmarshal([]byte(val), &valDecoded); err != nil { if err = json.Unmarshal([]byte(val), &valDecoded); err != nil {
s.log.Print(err) log.Print(err)
continue continue
} }
result[key] = valDecoded result[key] = valDecoded
@ -74,7 +77,7 @@ func (s *Storage) UpdateSettings(kv map[string]interface{}) bool {
} }
valEncoded, err := json.Marshal(val) valEncoded, err := json.Marshal(val)
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return false return false
} }
_, err = s.db.Exec(` _, err = s.db.Exec(`
@ -83,7 +86,7 @@ func (s *Storage) UpdateSettings(kv map[string]interface{}) bool {
key, valEncoded, valEncoded, key, valEncoded, valEncoded,
) )
if err != nil { if err != nil {
s.log.Print(err) log.Print(err)
return false return false
} }
} }

View File

@ -3,15 +3,13 @@ package storage
import ( import (
"database/sql" "database/sql"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"log"
) )
type Storage struct { type Storage struct {
db *sql.DB db *sql.DB
log *log.Logger
} }
func New(path string, log *log.Logger) (*Storage, error) { func New(path string) (*Storage, error) {
db, err := sql.Open("sqlite3", path) db, err := sql.Open("sqlite3", path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -19,8 +17,8 @@ func New(path string, log *log.Logger) (*Storage, error) {
db.SetMaxOpenConns(1) db.SetMaxOpenConns(1)
if err = migrate(db, log); err != nil { if err = migrate(db); err != nil {
return nil, err return nil, err
} }
return &Storage{db: db, log: log}, nil return &Storage{db: db}, nil
} }