diff --git a/backend/.env b/backend/.env index 5e9bd2d..5ae0b8b 100644 --- a/backend/.env +++ b/backend/.env @@ -1,3 +1,3 @@ OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf -OTEL_EXPORTER_OTLP_HEADERS='authorization=c6d415f0-7f6f-40ec-86b0-672dacd3bcfd' +OTEL_EXPORTER_OTLP_HEADERS='authorization=590f929c-5368-460d-ac52-dad6eeab04f7' diff --git a/backend/internal/store/song.go b/backend/internal/store/song.go index cb4097e..8984e9d 100644 --- a/backend/internal/store/song.go +++ b/backend/internal/store/song.go @@ -5,7 +5,6 @@ import ( "database/sql" "errors" "fmt" - "log/slog" m "echsen.club/radio/internal/models" "echsen.club/radio/internal/otel" diff --git a/backend/internal/store/user.go b/backend/internal/store/user.go index db644e2..40cb1fd 100644 --- a/backend/internal/store/user.go +++ b/backend/internal/store/user.go @@ -2,37 +2,75 @@ package store import ( "context" + "database/sql" + "errors" "fmt" - "log/slog" "echsen.club/radio/internal/models" m "echsen.club/radio/internal/models" + "echsen.club/radio/internal/otel" "github.com/google/uuid" + "github.com/samber/lo" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" ) func (s *Store) GetUser(ctx context.Context, id uuid.UUID) (*m.User, error) { + rootSpan := otel.GetRootSpan(ctx) + rootSpan.SetAttributes(attribute.String("user.id", id.String())) + var u m.User query := `SELECT id, subject_id, email, display_name FROM users WHERE id = $1` err := s.db.QueryRowContext(ctx, query, id).Scan(&u.ID, &u.SubjectID, &u.Email, &u.DisplayName) if err != nil { + if errors.Is(err, sql.ErrNoRows) { + rootSpan.SetAttributes( + attribute.String("user.status", "not_found"), + ) + return nil, fmt.Errorf("user not found") + } + rootSpan.RecordError(err) + rootSpan.SetStatus(codes.Error, "user_get_failed") return nil, err } + + rootSpan.SetAttributes( + attribute.Int64("user.created_at", u.CreatedAt.Unix()), + attribute.String("user.created_at_fmt", u.CreatedAt.String()), + attribute.Int64("user.last_login", u.LastLogin.Unix()), + attribute.String("user.last_login_fmt", u.LastLogin.String()), + ) + return &u, nil } func (s *Store) GetPublicUser(ctx context.Context, id uuid.UUID) (*m.PublicUser, error) { + rootSpan := otel.GetRootSpan(ctx) + rootSpan.SetAttributes(attribute.String("user.id", id.String())) + var u m.PublicUser query := `SELECT id, display_name FROM users WHERE id = $1` err := s.db.QueryRowContext(ctx, query, id).Scan(&u.ID, &u.DisplayName) if err != nil { + if errors.Is(err, sql.ErrNoRows) { + rootSpan.SetAttributes( + attribute.String("user.status", "not_found"), + ) + return nil, fmt.Errorf("user not found") + } + rootSpan.RecordError(err) + rootSpan.SetStatus(codes.Error, "user_get_failed") return nil, err } + return &u, nil } func (s *Store) Upsert(ctx context.Context, subjectID, email, name string) (uuid.UUID, error) { + rootSpan := otel.GetRootSpan(ctx) + var id uuid.UUID // ON CONFLICT (subject_id) tells Postgres: "If this OIDC user already exists, @@ -49,20 +87,35 @@ func (s *Store) Upsert(ctx context.Context, subjectID, email, name string) (uuid err := s.db.QueryRowContext(ctx, query, subjectID, email, name).Scan(&id) if err != nil { + rootSpan.RecordError(err) + rootSpan.SetStatus(codes.Error, "user_upsert_failed") return uuid.Nil, fmt.Errorf("failed to upsert user: %w", err) } + rootSpan.SetAttributes( + attribute.String("user.id", id.String()), + ) + return id, nil } func (s *Store) ListUsers(ctx context.Context) ([]models.PublicUser, error) { + rootSpan := otel.GetRootSpan(ctx) + var users []models.PublicUser err := s.db.SelectContext(ctx, &users, `SELECT id, display_name from users`) if err != nil { - slog.Error("couldnt list users", "error", err) + rootSpan.RecordError(err) + rootSpan.SetStatus(codes.Error, "user_list_failed") return nil, fmt.Errorf("couldnt list users") } + rootSpan.SetAttributes( + attribute.StringSlice("user.list.ids", lo.Map(users, func(u m.PublicUser, _ int) string { + return u.ID.String() + })), + ) + return users, nil } diff --git a/justfile b/justfile index cf37c1d..efed206 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,9 @@ start-backend: cd backend && air +start-frontend: + cd frontend && npm run dev + generate: buf generate