Expose Prometheus metrics on a separate port
CI / integration (push) Failing after 14s
CI / docker (push) Failing after 20s
CI / test (push) Successful in 1m10s
CI / publish (push) Skipped

Metrics are served on METRICS_PORT (default 2112, "off" to disable), never on
the public port. Besides the Go runtime and process metrics this adds:

- http_requests_total and http_request_duration_seconds per route pattern,
  from an Echo middleware.
- musicserver_songs_requested_total and musicserver_songs_played_total by
  pick mode (random, low, classic). The mode is now stored with each queued
  song (migration 000006, not released yet).
- Library size, sync duration, last successful sync, broken songs from the
  last full sync, and the database connection pool.

Refs #35, #36, #37

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
SansanandClaude Opus 5.5 committed 2026-10-11 21:57:58 +02:00
1 parent c62b65d7cd
commit f79f51ea4c
28 files changed
+864 -70

No files matched your search

+13 -8
View File
@@ -13,17 +13,17 @@ import (
const addLastFetchedToQueue = `-- name: AddLastFetchedToQueue :exec
WITH added AS (
INSERT INTO queue_song (queue_uuid, song_no, song_uuid, soundtrack_name, song_name)
INSERT INTO queue_song (queue_uuid, song_no, song_uuid, soundtrack_name, song_name, mode)
SELECT q.uuid,
(SELECT COALESCE(MAX(qs.song_no), -1) + 1 FROM queue_song qs WHERE qs.queue_uuid = q.uuid),
s.uuid, st.soundtrack_name, s.song_name
s.uuid, st.soundtrack_name, s.song_name, COALESCE(q.last_fetched_mode, 'unknown')
FROM queue q
JOIN song s ON s.uuid = q.last_fetched_song_uuid
JOIN soundtrack st ON st.id = s.soundtrack_id
WHERE q.uuid = $1
RETURNING queue_uuid, song_no
)
UPDATE queue SET current_song = added.song_no, last_fetched_song_uuid = NULL
UPDATE queue SET current_song = added.song_no, last_fetched_song_uuid = NULL, last_fetched_mode = NULL
FROM added
WHERE queue.uuid = added.queue_uuid
`
@@ -37,7 +37,7 @@ func (q *Queries) AddLastFetchedToQueue(ctx context.Context, argUuid uuid.UUID)
const createQueue = `-- name: CreateQueue :one
INSERT INTO queue DEFAULT VALUES
RETURNING uuid, current_song, last_fetched_song_uuid, started_at, ended_at
RETURNING uuid, current_song, last_fetched_song_uuid, last_fetched_mode, started_at, ended_at
`
func (q *Queries) CreateQueue(ctx context.Context) (Queue, error) {
@@ -47,6 +47,7 @@ func (q *Queries) CreateQueue(ctx context.Context) (Queue, error) {
&i.Uuid,
&i.CurrentSong,
&i.LastFetchedSongUuid,
&i.LastFetchedMode,
&i.StartedAt,
&i.EndedAt,
)
@@ -74,7 +75,7 @@ func (q *Queries) EndQueue(ctx context.Context, argUuid uuid.UUID) error {
}
const getQueue = `-- name: GetQueue :one
SELECT uuid, current_song, last_fetched_song_uuid, started_at, ended_at
SELECT uuid, current_song, last_fetched_song_uuid, last_fetched_mode, started_at, ended_at
FROM queue
WHERE uuid = $1
`
@@ -86,6 +87,7 @@ func (q *Queries) GetQueue(ctx context.Context, argUuid uuid.UUID) (Queue, error
&i.Uuid,
&i.CurrentSong,
&i.LastFetchedSongUuid,
&i.LastFetchedMode,
&i.StartedAt,
&i.EndedAt,
)
@@ -93,7 +95,7 @@ func (q *Queries) GetQueue(ctx context.Context, argUuid uuid.UUID) (Queue, error
}
const listQueueSongs = `-- name: ListQueueSongs :many
SELECT qs.song_no, qs.song_uuid, qs.soundtrack_name, qs.song_name,
SELECT qs.song_no, qs.song_uuid, qs.soundtrack_name, qs.song_name, qs.mode,
s.path, s.times_played, s.soundtrack_uuid
FROM queue_song qs
LEFT JOIN song s ON s.uuid = qs.song_uuid
@@ -106,6 +108,7 @@ type ListQueueSongsRow struct {
SongUuid uuid.UUID `json:"song_uuid"`
SoundtrackName string `json:"soundtrack_name"`
SongName string `json:"song_name"`
Mode string `json:"mode"`
Path *string `json:"path"`
TimesPlayed *int32 `json:"times_played"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
@@ -126,6 +129,7 @@ func (q *Queries) ListQueueSongs(ctx context.Context, queueUuid uuid.UUID) ([]Li
&i.SongUuid,
&i.SoundtrackName,
&i.SongName,
&i.Mode,
&i.Path,
&i.TimesPlayed,
&i.SoundtrackUuid,
@@ -156,16 +160,17 @@ func (q *Queries) SetQueueCurrentSong(ctx context.Context, arg SetQueueCurrentSo
}
const setQueueLastFetched = `-- name: SetQueueLastFetched :exec
UPDATE queue SET last_fetched_song_uuid = $2
UPDATE queue SET last_fetched_song_uuid = $2, last_fetched_mode = $3
WHERE uuid = $1
`
type SetQueueLastFetchedParams struct {
Uuid uuid.UUID `json:"uuid"`
LastFetchedSongUuid uuid.UUID `json:"last_fetched_song_uuid"`
LastFetchedMode *string `json:"last_fetched_mode"`
}
func (q *Queries) SetQueueLastFetched(ctx context.Context, arg SetQueueLastFetchedParams) error {
_, err := q.db.Exec(ctx, setQueueLastFetched, arg.Uuid, arg.LastFetchedSongUuid)
_, err := q.db.Exec(ctx, setQueueLastFetched, arg.Uuid, arg.LastFetchedSongUuid, arg.LastFetchedMode)
return err
}