fix(insights): fix issues and improve reports (#3558)

* fix(insights): show error whn reading library counts

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(insights): wait 30 mins before send first report

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(insights): send number of active players, grouped by client type

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(insights): disable reports when running in dev mode

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(insights): add Dockerfile to the docker build, to avoid `vcs.modified=true`

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(insights): add more linux fs types

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(insights): need admin permissions to retrieve library counts

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(insights): dev flag to disable player insights

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan Quintão 2024-12-18 20:37:35 -05:00 committed by GitHub
parent 4f8cd5307c
commit 6c11649b06
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 103 additions and 29 deletions

View file

@ -16,6 +16,7 @@ import (
"github.com/google/uuid"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/core/auth"
"github.com/navidrome/navidrome/core/metrics/insights"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
@ -54,6 +55,7 @@ func GetInstance(ds model.DataStore) Insights {
}
func (c *insightsCollector) Run(ctx context.Context) {
ctx = auth.WithAdminUser(ctx, c.ds)
for {
c.sendInsights(ctx)
select {
@ -199,15 +201,45 @@ func (c *insightsCollector) collect(ctx context.Context) []byte {
data.Uptime = time.Since(consts.ServerStart).Milliseconds() / 1000
// Library info
data.Library.Tracks, _ = c.ds.MediaFile(ctx).CountAll()
data.Library.Albums, _ = c.ds.Album(ctx).CountAll()
data.Library.Artists, _ = c.ds.Artist(ctx).CountAll()
data.Library.Playlists, _ = c.ds.Playlist(ctx).Count()
data.Library.Shares, _ = c.ds.Share(ctx).CountAll()
data.Library.Radios, _ = c.ds.Radio(ctx).Count()
data.Library.ActiveUsers, _ = c.ds.User(ctx).CountAll(model.QueryOptions{
var err error
data.Library.Tracks, err = c.ds.MediaFile(ctx).CountAll()
if err != nil {
log.Trace(ctx, "Error reading tracks count", err)
}
data.Library.Albums, err = c.ds.Album(ctx).CountAll()
if err != nil {
log.Trace(ctx, "Error reading albums count", err)
}
data.Library.Artists, err = c.ds.Artist(ctx).CountAll()
if err != nil {
log.Trace(ctx, "Error reading artists count", err)
}
data.Library.Playlists, err = c.ds.Playlist(ctx).CountAll()
if err != nil {
log.Trace(ctx, "Error reading playlists count", err)
}
data.Library.Shares, err = c.ds.Share(ctx).CountAll()
if err != nil {
log.Trace(ctx, "Error reading shares count", err)
}
data.Library.Radios, err = c.ds.Radio(ctx).Count()
if err != nil {
log.Trace(ctx, "Error reading radios count", err)
}
data.Library.ActiveUsers, err = c.ds.User(ctx).CountAll(model.QueryOptions{
Filters: squirrel.Gt{"last_access_at": time.Now().Add(-7 * 24 * time.Hour)},
})
if err != nil {
log.Trace(ctx, "Error reading active users count", err)
}
if conf.Server.DevEnablePlayerInsights {
data.Library.ActivePlayers, err = c.ds.Player(ctx).CountByClient(model.QueryOptions{
Filters: squirrel.Gt{"last_seen": time.Now().Add(-7 * 24 * time.Hour)},
})
if err != nil {
log.Trace(ctx, "Error reading active players count", err)
}
}
// Memory info
var m runtime.MemStats

View file

@ -29,13 +29,14 @@ type Data struct {
Backup *FSInfo `json:"backup,omitempty"`
} `json:"fs"`
Library struct {
Tracks int64 `json:"tracks"`
Albums int64 `json:"albums"`
Artists int64 `json:"artists"`
Playlists int64 `json:"playlists"`
Shares int64 `json:"shares"`
Radios int64 `json:"radios"`
ActiveUsers int64 `json:"activeUsers"`
Tracks int64 `json:"tracks"`
Albums int64 `json:"albums"`
Artists int64 `json:"artists"`
Playlists int64 `json:"playlists"`
Shares int64 `json:"shares"`
Radios int64 `json:"radios"`
ActiveUsers int64 `json:"activeUsers"`
ActivePlayers map[string]int64 `json:"activePlayers"`
} `json:"library"`
Config struct {
LogLevel string `json:"logLevel,omitempty"`

View file

@ -41,22 +41,29 @@ type MountInfo struct {
}
var fsTypeMap = map[int64]string{
// Add filesystem type mappings
0x5346414f: "afs",
0x61756673: "aufs",
0x9123683E: "btrfs",
0x0000EF53: "ext2/ext3/ext4",
0x00006969: "nfs",
0x58465342: "xfs",
0x2FC12FC1: "zfs",
0x01021994: "tmpfs",
0x28cd3d45: "cramfs",
0x64626720: "debugfs",
0x0000EF53: "ext2/ext3/ext4",
0x6a656a63: "fakeowner", // FS inside a container
0x65735546: "fuse",
0x4244: "hfs",
0x9660: "iso9660",
0x3153464a: "jfs",
0x00006969: "nfs",
0x794c7630: "overlayfs",
0x9fa0: "proc",
0x517b: "smb",
0xfe534d42: "smb2",
0x73717368: "squashfs",
0x62656572: "sysfs",
0x9fa0: "proc",
0x61756673: "aufs",
0x794c7630: "overlayfs",
0x6a656a63: "fakeowner", // FS inside a container
// Include other filesystem types as needed
0x01021994: "tmpfs",
0x01021997: "v9fs",
0x4d44: "vfat",
0x58465342: "xfs",
0x2FC12FC1: "zfs",
}
func getFilesystemType(path string) (string, error) {