From 4300d45482539f4b19752abc7f41fe40588e076b Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Tue, 19 May 2020 13:48:05 +0200 Subject: [PATCH] Backend: Log errors in database Signed-off-by: Michael Mayer --- internal/config/db.go | 2 + internal/entity/entity.go | 1 + internal/entity/error.go | 51 ++++++++++++++++++++++++++ internal/entity/photo.go | 4 +- internal/entity/photo_fixtures.go | 22 +++++------ internal/entity/photo_test.go | 12 +++++- internal/photoprism/index_mediafile.go | 2 +- 7 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 internal/entity/error.go diff --git a/internal/config/db.go b/internal/config/db.go index f5dd9c252..263a561b9 100644 --- a/internal/config/db.go +++ b/internal/config/db.go @@ -59,12 +59,14 @@ func (c *Config) CloseDb() error { func (c *Config) InitDb() { entity.SetDbProvider(c) entity.MigrateDb() + go entity.SaveErrorMessages() } // InitTestDb drops all tables in the currently configured database and re-creates them. func (c *Config) InitTestDb() { entity.SetDbProvider(c) entity.ResetTestFixtures() + go entity.SaveErrorMessages() } // connectToDatabase establishes a database connection. diff --git a/internal/entity/entity.go b/internal/entity/entity.go index 28ebbc4c5..5ee3cbbc3 100644 --- a/internal/entity/entity.go +++ b/internal/entity/entity.go @@ -29,6 +29,7 @@ type Types map[string]interface{} // List of database entities and their table names. var Entities = Types{ + "errors": &Error{}, "accounts": &Account{}, "files": &File{}, "files_share": &FileShare{}, diff --git a/internal/entity/error.go b/internal/entity/error.go new file mode 100644 index 000000000..aaf5d5ed8 --- /dev/null +++ b/internal/entity/error.go @@ -0,0 +1,51 @@ +package entity + +import ( + "time" + + "github.com/photoprism/photoprism/internal/event" + "github.com/sirupsen/logrus" +) + +// Error represents an error message log. +type Error struct { + ID uint `gorm:"primary_key"` + ErrorTime time.Time `sql:"index"` + ErrorLevel string `gorm:"type:varbinary(32)"` + ErrorMessage string `gorm:"type:varbinary(2048)"` +} + +// SaveErrorMessages subscribes to error logs and stored them in the errors table. +func SaveErrorMessages() { + s := event.Subscribe("log.*") + + defer func() { + event.Unsubscribe(s) + }() + + for msg := range s.Receiver { + level, ok := msg.Fields["level"] + + if !ok { + continue + } + + logLevel, err := logrus.ParseLevel(level.(string)) + + if err != nil || logLevel >= logrus.InfoLevel { + continue + } + + newError := Error{ErrorLevel: logLevel.String()} + + if val, ok := msg.Fields["msg"]; ok { + newError.ErrorMessage = val.(string) + } + + if val, ok := msg.Fields["time"]; ok { + newError.ErrorTime = val.(time.Time) + } + + Db().Create(&newError) + } +} diff --git a/internal/entity/photo.go b/internal/entity/photo.go index 1b237e117..54f7bb18c 100644 --- a/internal/entity/photo.go +++ b/internal/entity/photo.go @@ -106,7 +106,7 @@ func SavePhotoForm(model Photo, form form.Photo, geoApi string) error { } if err := model.IndexKeywords(); err != nil { - log.Warnf("%s (%s)", err.Error(), model.PhotoUUID) + log.Error(err) } edited := time.Now().UTC() @@ -219,7 +219,7 @@ func (m *Photo) BeforeSave(scope *gorm.Scope) error { // IndexKeywords adds given keywords to the photo entry func (m *Photo) IndexKeywords() error { if !m.DetailsLoaded() { - return fmt.Errorf("photo: can't index keywords, description not loaded (%s)", m.PhotoUUID) + return fmt.Errorf("photo: can't index keywords, details not loaded (%s)", m.PhotoUUID) } db := Db() diff --git a/internal/entity/photo_fixtures.go b/internal/entity/photo_fixtures.go index 1bd64a6bf..ad50ed14c 100644 --- a/internal/entity/photo_fixtures.go +++ b/internal/entity/photo_fixtures.go @@ -117,7 +117,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2790, PhotoMonth: 2, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000001), DescriptionSrc: "", Camera: CameraFixtures.Pointer("canon-eos-6d"), Lens: LensFixtures.Pointer("lens-f-380"), @@ -166,7 +166,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 1990, PhotoMonth: 3, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000002), DescriptionSrc: "", Camera: nil, Lens: LensFixtures.Pointer("lens-f-380"), @@ -215,7 +215,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 1990, PhotoMonth: 4, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000003), DescriptionSrc: "", Camera: nil, Lens: nil, @@ -267,7 +267,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000004), DescriptionSrc: "", Camera: CameraFixtures.Pointer("canon-eos-6d"), Lens: LensFixtures.Pointer("lens-f-380"), @@ -320,7 +320,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000005), DescriptionSrc: "", Camera: CameraFixtures.Pointer("canon-eos-6d"), Lens: LensFixtures.Pointer("lens-f-380"), @@ -369,7 +369,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000006), DescriptionSrc: "", Camera: nil, Lens: nil, @@ -418,7 +418,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000007), DescriptionSrc: "", Camera: nil, Lens: nil, @@ -467,7 +467,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000008), DescriptionSrc: "", Camera: nil, Lens: nil, @@ -516,7 +516,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 1000009), DescriptionSrc: "", Camera: nil, Lens: nil, @@ -565,7 +565,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 10000010), DescriptionSrc: "", Camera: nil, Lens: nil, @@ -614,7 +614,7 @@ var PhotoFixtures = PhotoMap{ PhotoCountry: "zz", PhotoYear: 2014, PhotoMonth: 7, - Details: Details{}, + Details: DetailsFixtures.Get("lake", 10000011), DescriptionSrc: "", Camera: nil, Lens: nil, diff --git a/internal/entity/photo_test.go b/internal/entity/photo_test.go index 8bbb32c08..4d2b6ece1 100644 --- a/internal/entity/photo_test.go +++ b/internal/entity/photo_test.go @@ -97,7 +97,15 @@ func TestPhoto_Save(t *testing.T) { PlaceID: "765", PhotoCountry: "de", Keywords: []Keyword{}, - Details: Details{}, + Details: Details{ + PhotoID: 11111, + Keywords: "test cat dog", + Subject: "animals", + Artist: "Bender", + Notes: "notes", + Copyright: "copy", + License: "", + }, } err := photo.Save() @@ -276,7 +284,7 @@ func TestPhoto_DetailsLoaded(t *testing.T) { assert.True(t, m.DetailsLoaded()) }) t.Run("false", func(t *testing.T) { - m := PhotoFixtures.Get("Photo05") + m := PhotoFixtures.Get("Photo12") assert.False(t, m.DetailsLoaded()) }) } diff --git a/internal/photoprism/index_mediafile.go b/internal/photoprism/index_mediafile.go index e75794fe6..5e885ca85 100644 --- a/internal/photoprism/index_mediafile.go +++ b/internal/photoprism/index_mediafile.go @@ -431,7 +431,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) ( } if err := photo.IndexKeywords(); err != nil { - log.Warnf("%s (%s)", err.Error(), photo.PhotoUUID) + log.Error(err) } } else { if photo.PhotoQuality >= 0 {