diff --git a/app.env.example b/app.env.example index d21de08..50c794b 100644 --- a/app.env.example +++ b/app.env.example @@ -14,3 +14,5 @@ AWS_ACCESS_KEY_ID=example AWS_SECRET_ACCESS_KEY=example AWS_REGION=example S3_BUCKET_NAME=example + +SENTRY_DSN=https://id@anotherid.ingest.sentry.io/numeric-id diff --git a/cmd/app/config.go b/cmd/app/config.go index 4346bcf..5e84fcf 100644 --- a/cmd/app/config.go +++ b/cmd/app/config.go @@ -18,6 +18,7 @@ type AppConfig struct { AwsSecretAccessKey string `mapstructure:"AWS_SECRET_ACCESS_KEY"` AwsRegion string `mapstructure:"AWS_REGION"` S3BucketName string `mapstructure:"S3_BUCKET_NAME"` + SentryDSN string `mapstructure:"SENTRY_DSN"` } func ReadConfig() (*AppConfig, error) { diff --git a/cmd/app/main.go b/cmd/app/main.go index 1a07a94..db21f2f 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -4,6 +4,7 @@ import ( "github.com/jibaru/home-inventory-api/m/internal/app/infrastructure/database" "github.com/jibaru/home-inventory-api/m/internal/app/infrastructure/http" "github.com/jibaru/home-inventory-api/m/logger" + "github.com/jibaru/home-inventory-api/m/notifier" "strconv" "time" ) @@ -15,6 +16,13 @@ func main() { return } + err = notifier.Init(config.SentryDSN) + if err != nil { + logger.LogError(err) + return + } + defer notifier.Flush() + db, err := database.CreateConnection( database.DBConfig{ Name: config.DatabaseName, diff --git a/go.mod b/go.mod index 2ba1e5f..1a5463c 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect diff --git a/go.sum b/go.sum index 898a2de..d0b01e1 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= diff --git a/internal/app/infrastructure/repositories/gorm/asset.go b/internal/app/infrastructure/repositories/gorm/asset.go index 30b8b19..7480550 100644 --- a/internal/app/infrastructure/repositories/gorm/asset.go +++ b/internal/app/infrastructure/repositories/gorm/asset.go @@ -4,6 +4,7 @@ import ( "github.com/jibaru/home-inventory-api/m/internal/app/domain/entities" "github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories" "github.com/jibaru/home-inventory-api/m/logger" + "github.com/jibaru/home-inventory-api/m/notifier" "gorm.io/gorm" ) @@ -20,6 +21,7 @@ func NewAssetRepository(db *gorm.DB) *AssetRepository { func (r *AssetRepository) Create(asset *entities.Asset) error { if err := r.db.Create(asset).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrAssetRepositoryCanNotCreateAsset } @@ -43,6 +45,7 @@ func (r *AssetRepository) FindByEntity( if err := result.Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return nil, repositories.ErrAssetRepositoryCanNotGetAssets } @@ -52,6 +55,7 @@ func (r *AssetRepository) FindByEntity( func (r *AssetRepository) Delete(id string) error { if err := r.db.Delete(&entities.Asset{}, "id = ?", id).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrAssetRepositoryCanNotDeleteAsset } @@ -64,6 +68,7 @@ func (r *AssetRepository) GetByQueryFilters(queryFilter repositories.QueryFilter if err := result.Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return nil, repositories.ErrorAssetRepositoryCanNotGetByQueryFilters } diff --git a/internal/app/infrastructure/repositories/gorm/box.go b/internal/app/infrastructure/repositories/gorm/box.go index 04f96da..7379ad2 100644 --- a/internal/app/infrastructure/repositories/gorm/box.go +++ b/internal/app/infrastructure/repositories/gorm/box.go @@ -4,6 +4,7 @@ import ( "github.com/jibaru/home-inventory-api/m/internal/app/domain/entities" "github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories" "github.com/jibaru/home-inventory-api/m/logger" + "github.com/jibaru/home-inventory-api/m/notifier" "gorm.io/gorm" ) @@ -17,6 +18,8 @@ func NewBoxRepository(db *gorm.DB) *BoxRepository { func (r *BoxRepository) Create(box *entities.Box) error { if err := r.db.Create(box).Error; err != nil { + logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanNotCreateBox } @@ -37,6 +40,7 @@ func (r *BoxRepository) GetBoxItem(boxID string, itemID string) (*entities.BoxIt func (r *BoxRepository) CreateBoxItem(boxItem *entities.BoxItem) error { if err := r.db.Create(boxItem).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanBotCreateBoxItem } @@ -46,6 +50,7 @@ func (r *BoxRepository) CreateBoxItem(boxItem *entities.BoxItem) error { func (r *BoxRepository) UpdateBoxItem(boxItem *entities.BoxItem) error { if err := r.db.Save(boxItem).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanNotUpdateBoxItem } @@ -55,6 +60,7 @@ func (r *BoxRepository) UpdateBoxItem(boxItem *entities.BoxItem) error { func (r *BoxRepository) CreateBoxTransaction(boxTransaction *entities.BoxTransaction) error { if err := r.db.Create(boxTransaction).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanNotCreateBoxTransaction } @@ -64,6 +70,7 @@ func (r *BoxRepository) CreateBoxTransaction(boxTransaction *entities.BoxTransac func (r *BoxRepository) DeleteBoxItem(boxID string, itemID string) error { if err := r.db.Where("box_id = ? AND item_id = ?", boxID, itemID).Delete(&entities.BoxItem{}).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanNotDeleteBoxItem } @@ -105,6 +112,7 @@ func (r *BoxRepository) CountByQueryFilters(queryFilter repositories.QueryFilter func (r *BoxRepository) DeleteBoxItemsByBoxID(boxID string) error { if err := r.db.Where("box_id = ?", boxID).Delete(&entities.BoxItem{}).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanNotDeleteBoxItemsByBoxID } @@ -114,6 +122,7 @@ func (r *BoxRepository) DeleteBoxItemsByBoxID(boxID string) error { func (r *BoxRepository) DeleteBoxTransactionsByBoxID(boxID string) error { if err := r.db.Where("box_id = ?", boxID).Delete(&entities.BoxTransaction{}).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanNotDeleteBoxTransactionsByBoxID } @@ -123,6 +132,7 @@ func (r *BoxRepository) DeleteBoxTransactionsByBoxID(boxID string) error { func (r *BoxRepository) Delete(id string) error { if err := r.db.Where("id = ?", id).Delete(&entities.Box{}).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrBoxRepositoryCanNotDeleteBox } diff --git a/internal/app/infrastructure/repositories/gorm/item.go b/internal/app/infrastructure/repositories/gorm/item.go index a134c70..1f6ae74 100644 --- a/internal/app/infrastructure/repositories/gorm/item.go +++ b/internal/app/infrastructure/repositories/gorm/item.go @@ -4,6 +4,7 @@ import ( "github.com/jibaru/home-inventory-api/m/internal/app/domain/entities" "github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories" "github.com/jibaru/home-inventory-api/m/logger" + "github.com/jibaru/home-inventory-api/m/notifier" "gorm.io/gorm" ) @@ -20,6 +21,7 @@ func NewItemRepository(db *gorm.DB) *ItemRepository { func (r *ItemRepository) Create(item *entities.Item) error { if err := r.db.Create(item).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrItemRepositoryCanNotCreateItem } diff --git a/internal/app/infrastructure/repositories/gorm/item_keyword.go b/internal/app/infrastructure/repositories/gorm/item_keyword.go index 6c46210..74b1b0a 100644 --- a/internal/app/infrastructure/repositories/gorm/item_keyword.go +++ b/internal/app/infrastructure/repositories/gorm/item_keyword.go @@ -4,6 +4,7 @@ import ( "github.com/jibaru/home-inventory-api/m/internal/app/domain/entities" "github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories" "github.com/jibaru/home-inventory-api/m/logger" + "github.com/jibaru/home-inventory-api/m/notifier" "gorm.io/gorm" ) @@ -20,6 +21,7 @@ func NewItemKeywordRepository(db *gorm.DB) *ItemKeywordRepository { func (r *ItemKeywordRepository) CreateMany(itemKeywords []*entities.ItemKeyword) error { if err := r.db.Create(&itemKeywords).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrItemKeywordRepositoryCanNotCreateItemKeywords } diff --git a/internal/app/infrastructure/repositories/gorm/room.go b/internal/app/infrastructure/repositories/gorm/room.go index 467d26d..8d8c9a9 100644 --- a/internal/app/infrastructure/repositories/gorm/room.go +++ b/internal/app/infrastructure/repositories/gorm/room.go @@ -4,6 +4,7 @@ import ( "github.com/jibaru/home-inventory-api/m/internal/app/domain/entities" "github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories" "github.com/jibaru/home-inventory-api/m/logger" + "github.com/jibaru/home-inventory-api/m/notifier" "gorm.io/gorm" ) @@ -20,6 +21,7 @@ func NewRoomRepository(db *gorm.DB) *RoomRepository { func (r *RoomRepository) Create(room *entities.Room) error { if err := r.db.Create(room).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrRoomRepositoryCanNotCreateRoom } @@ -74,6 +76,7 @@ func (r *RoomRepository) Delete(id string) error { err := r.db.Where("id = ?", id).Delete(&entities.Room{}).Error if err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrRoomRepositoryCanNotDeleteRoom } diff --git a/internal/app/infrastructure/repositories/gorm/user.go b/internal/app/infrastructure/repositories/gorm/user.go index 0b92656..9e3402b 100644 --- a/internal/app/infrastructure/repositories/gorm/user.go +++ b/internal/app/infrastructure/repositories/gorm/user.go @@ -5,6 +5,7 @@ import ( "github.com/jibaru/home-inventory-api/m/internal/app/domain/entities" "github.com/jibaru/home-inventory-api/m/internal/app/domain/repositories" "github.com/jibaru/home-inventory-api/m/logger" + "github.com/jibaru/home-inventory-api/m/notifier" "gorm.io/gorm" ) @@ -21,6 +22,7 @@ func NewUserRepository(db *gorm.DB) *UserRepository { func (r *UserRepository) Create(user *entities.User) error { if err := r.db.Create(user).Error; err != nil { logger.LogError(err) + notifier.NotifyError(err) return repositories.ErrUserRepositoryCanNotCreateUser } diff --git a/notifier/notifier.go b/notifier/notifier.go new file mode 100644 index 0000000..aae783a --- /dev/null +++ b/notifier/notifier.go @@ -0,0 +1,35 @@ +package notifier + +import ( + "github.com/getsentry/sentry-go" + "time" +) + +var configured bool + +func Init(dsn string) error { + err := sentry.Init(sentry.ClientOptions{ + Dsn: dsn, + Debug: true, + AttachStacktrace: true, + }) + if err != nil { + return err + } + + configured = true + + return nil +} + +// Flush buffered events before the program terminates. +// Set the timeout to the maximum duration the program can afford to wait. +func Flush() { + sentry.Flush(2 * time.Second) +} + +func NotifyError(err error) { + if configured { + sentry.CaptureException(err) + } +}