appview: improve the logging situation a bit #654

closed
opened by oppi.li targeting master from push-nsovyllpxlwk

needs a lot more work, but we now inject slog in several places.

Signed-off-by: oppiliappan me@oppi.li

Changed files
+414 -228
appview
cmd
appview
jetstream
nix
xrpc
serviceauth
+36 -28
appview/db/db.go
···
"context"
"database/sql"
"fmt"
-
"log"
+
"log/slog"
"reflect"
"strings"
_ "github.com/mattn/go-sqlite3"
+
"tangled.org/core/log"
)
type DB struct {
*sql.DB
+
logger *slog.Logger
}
type Execer interface {
···
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
}
-
func Make(dbPath string) (*DB, error) {
+
func Make(ctx context.Context, dbPath string) (*DB, error) {
// https://github.com/mattn/go-sqlite3#connection-string
opts := []string{
"_foreign_keys=1",
···
"_auto_vacuum=incremental",
}
+
logger := log.FromContext(ctx)
+
logger = log.SubLogger(logger, "db")
+
db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&"))
if err != nil {
return nil, err
}
-
ctx := context.Background()
-
conn, err := db.Conn(ctx)
if err != nil {
return nil, err
···
}
// run migrations
-
runMigration(conn, "add-description-to-repos", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-description-to-repos", func(tx *sql.Tx) error {
tx.Exec(`
alter table repos add column description text check (length(description) <= 200);
`)
return nil
})
-
runMigration(conn, "add-rkey-to-pubkeys", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-rkey-to-pubkeys", func(tx *sql.Tx) error {
// add unconstrained column
_, err := tx.Exec(`
alter table public_keys
···
return nil
})
-
runMigration(conn, "add-rkey-to-comments", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-rkey-to-comments", func(tx *sql.Tx) error {
_, err := tx.Exec(`
alter table comments drop column comment_at;
alter table comments add column rkey text;
···
return err
})
-
runMigration(conn, "add-deleted-and-edited-to-issue-comments", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-deleted-and-edited-to-issue-comments", func(tx *sql.Tx) error {
_, err := tx.Exec(`
alter table comments add column deleted text; -- timestamp
alter table comments add column edited text; -- timestamp
···
return err
})
-
runMigration(conn, "add-source-info-to-pulls-and-submissions", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-source-info-to-pulls-and-submissions", func(tx *sql.Tx) error {
_, err := tx.Exec(`
alter table pulls add column source_branch text;
alter table pulls add column source_repo_at text;
···
return err
})
-
runMigration(conn, "add-source-to-repos", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-source-to-repos", func(tx *sql.Tx) error {
_, err := tx.Exec(`
alter table repos add column source text;
`)
···
//
// [0]: https://sqlite.org/pragma.html#pragma_foreign_keys
conn.ExecContext(ctx, "pragma foreign_keys = off;")
-
runMigration(conn, "recreate-pulls-column-for-stacking-support", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "recreate-pulls-column-for-stacking-support", func(tx *sql.Tx) error {
_, err := tx.Exec(`
create table pulls_new (
-- identifiers
···
})
conn.ExecContext(ctx, "pragma foreign_keys = on;")
-
runMigration(conn, "add-spindle-to-repos", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-spindle-to-repos", func(tx *sql.Tx) error {
tx.Exec(`
alter table repos add column spindle text;
`)
···
// drop all knot secrets, add unique constraint to knots
//
// knots will henceforth use service auth for signed requests
-
runMigration(conn, "no-more-secrets", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "no-more-secrets", func(tx *sql.Tx) error {
_, err := tx.Exec(`
create table registrations_new (
id integer primary key autoincrement,
···
})
// recreate and add rkey + created columns with default constraint
-
runMigration(conn, "rework-collaborators-table", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "rework-collaborators-table", func(tx *sql.Tx) error {
// create new table
// - repo_at instead of repo integer
// - rkey field
···
return err
})
-
runMigration(conn, "add-rkey-to-issues", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-rkey-to-issues", func(tx *sql.Tx) error {
_, err := tx.Exec(`
alter table issues add column rkey text not null default '';
···
})
// repurpose the read-only column to "needs-upgrade"
-
runMigration(conn, "rename-registrations-read-only-to-needs-upgrade", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "rename-registrations-read-only-to-needs-upgrade", func(tx *sql.Tx) error {
_, err := tx.Exec(`
alter table registrations rename column read_only to needs_upgrade;
`)
···
})
// require all knots to upgrade after the release of total xrpc
-
runMigration(conn, "migrate-knots-to-total-xrpc", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "migrate-knots-to-total-xrpc", func(tx *sql.Tx) error {
_, err := tx.Exec(`
update registrations set needs_upgrade = 1;
`)
···
})
// require all knots to upgrade after the release of total xrpc
-
runMigration(conn, "migrate-spindles-to-xrpc-owner", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "migrate-spindles-to-xrpc-owner", func(tx *sql.Tx) error {
_, err := tx.Exec(`
alter table spindles add column needs_upgrade integer not null default 0;
`)
···
//
// disable foreign-keys for the next migration
conn.ExecContext(ctx, "pragma foreign_keys = off;")
-
runMigration(conn, "remove-issue-at-from-issues", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "remove-issue-at-from-issues", func(tx *sql.Tx) error {
_, err := tx.Exec(`
create table if not exists issues_new (
-- identifiers
···
// - new columns
// * column "reply_to" which can be any other comment
// * column "at-uri" which is a generated column
-
runMigration(conn, "rework-issue-comments", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "rework-issue-comments", func(tx *sql.Tx) error {
_, err := tx.Exec(`
create table if not exists issue_comments (
-- identifiers
···
//
// disable foreign-keys for the next migration
conn.ExecContext(ctx, "pragma foreign_keys = off;")
-
runMigration(conn, "add-at-uri-to-pulls", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "add-at-uri-to-pulls", func(tx *sql.Tx) error {
_, err := tx.Exec(`
create table if not exists pulls_new (
-- identifiers
···
//
// disable foreign-keys for the next migration
conn.ExecContext(ctx, "pragma foreign_keys = off;")
-
runMigration(conn, "remove-repo-at-pull-id-from-pull-submissions", func(tx *sql.Tx) error {
+
runMigration(conn, logger, "remove-repo-at-pull-id-from-pull-submissions", func(tx *sql.Tx) error {
_, err := tx.Exec(`
create table if not exists pull_submissions_new (
-- identifiers
···
})
conn.ExecContext(ctx, "pragma foreign_keys = on;")
-
return &DB{db}, nil
+
return &DB{
+
db,
+
logger,
+
}, nil
type migrationFn = func(*sql.Tx) error
-
func runMigration(c *sql.Conn, name string, migrationFn migrationFn) error {
+
func runMigration(c *sql.Conn, logger *slog.Logger, name string, migrationFn migrationFn) error {
+
logger = logger.With("migration", name)
+
tx, err := c.BeginTx(context.Background(), nil)
if err != nil {
return err
···
// run migration
err = migrationFn(tx)
if err != nil {
-
log.Printf("Failed to run migration %s: %v", name, err)
+
logger.Error("failed to run migration", "err", err)
return err
// mark migration as complete
_, err = tx.Exec("insert into migrations (name) values (?)", name)
if err != nil {
-
log.Printf("Failed to mark migration %s as complete: %v", name, err)
+
logger.Error("failed to mark migration as complete", "err", err)
return err
···
return err
-
log.Printf("migration %s applied successfully", name)
+
logger.Info("migration applied successfully")
} else {
-
log.Printf("skipped migration %s, already applied", name)
+
logger.Warn("skipped migration, already applied")
return nil
+1 -1
appview/ingester.go
···
}
if err != nil {
-
l.Debug("error ingesting record", "err", err)
+
l.Warn("refused to ingest record", "err", err)
}
return nil
+27 -26
appview/issues/issues.go
···
"database/sql"
"errors"
"fmt"
-
"log"
"log/slog"
"net/http"
"slices"
···
"tangled.org/core/appview/reporesolver"
"tangled.org/core/appview/validator"
"tangled.org/core/idresolver"
-
tlog "tangled.org/core/log"
"tangled.org/core/tid"
)
···
config *config.Config,
notifier notify.Notifier,
validator *validator.Validator,
+
logger *slog.Logger,
) *Issues {
return &Issues{
oauth: oauth,
···
db: db,
config: config,
notifier: notifier,
-
logger: tlog.New("issues"),
+
logger: logger,
validator: validator,
}
}
···
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
db.FilterContains("scope", tangled.RepoIssueNSID),
)
if err != nil {
-
log.Println("failed to fetch labels", err)
+
l.Error("failed to fetch labels", "err", err)
rp.pages.Error503(w)
return
}
···
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
err = db.PutIssue(tx, newIssue)
if err != nil {
-
log.Println("failed to edit issue", err)
+
l.Error("failed to edit issue", "err", err)
rp.pages.Notice(w, "issues", "Failed to edit issue.")
return
}
···
// delete from PDS
client, err := rp.oauth.AuthorizedClient(r)
if err != nil {
-
log.Println("failed to get authorized client", err)
+
l.Error("failed to get authorized client", "err", err)
rp.pages.Notice(w, "issue-comment", "Failed to delete comment.")
return
}
···
collaborators, err := f.Collaborators(r.Context())
if err != nil {
-
log.Println("failed to fetch repo collaborators: %w", err)
+
l.Error("failed to fetch repo collaborators", "err", err)
}
isCollaborator := slices.ContainsFunc(collaborators, func(collab pages.Collaborator) bool {
return user.Did == collab.Did
···
db.FilterEq("id", issue.Id),
)
if err != nil {
-
log.Println("failed to close issue", err)
+
l.Error("failed to close issue", "err", err)
rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.")
return
}
···
rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId))
return
} else {
-
log.Println("user is not permitted to close issue")
+
l.Error("user is not permitted to close issue")
http.Error(w, "for biden", http.StatusUnauthorized)
return
}
···
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
collaborators, err := f.Collaborators(r.Context())
if err != nil {
-
log.Println("failed to fetch repo collaborators: %w", err)
+
l.Error("failed to fetch repo collaborators", "err", err)
}
isCollaborator := slices.ContainsFunc(collaborators, func(collab pages.Collaborator) bool {
return user.Did == collab.Did
···
db.FilterEq("id", issue.Id),
)
if err != nil {
-
log.Println("failed to reopen issue", err)
+
l.Error("failed to reopen issue", "err", err)
rp.pages.Notice(w, "issue-action", "Failed to reopen issue. Try again later.")
return
}
rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId))
return
} else {
-
log.Println("user is not the owner of the repo")
+
l.Error("user is not the owner of the repo")
http.Error(w, "forbidden", http.StatusUnauthorized)
return
}
···
newBody := r.FormValue("body")
client, err := rp.oauth.AuthorizedClient(r)
if err != nil {
-
log.Println("failed to get authorized client", err)
+
l.Error("failed to get authorized client", "err", err)
rp.pages.Notice(w, "issue-comment", "Failed to create comment.")
return
}
···
_, err = db.AddIssueComment(rp.db, newComment)
if err != nil {
-
log.Println("failed to perferom update-description query", err)
+
l.Error("failed to perferom update-description query", "err", err)
rp.pages.Notice(w, "repo-notice", "Failed to update description, try again later.")
return
}
···
// update the record on pds
ex, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.RepoIssueCommentNSID, user.Did, comment.Rkey)
if err != nil {
-
log.Println("failed to get record", "err", err, "did", newComment.Did, "rkey", newComment.Rkey)
+
l.Error("failed to get record", "err", err, "did", newComment.Did, "rkey", newComment.Rkey)
rp.pages.Notice(w, fmt.Sprintf("comment-%s-status", commentId), "Failed to update description, no record found on PDS.")
return
}
···
if comment.Rkey != "" {
client, err := rp.oauth.AuthorizedClient(r)
if err != nil {
-
log.Println("failed to get authorized client", err)
+
l.Error("failed to get authorized client", "err", err)
rp.pages.Notice(w, "issue-comment", "Failed to delete comment.")
return
}
···
Rkey: comment.Rkey,
})
if err != nil {
-
log.Println(err)
+
l.Error("failed to delete from PDS", "err", err)
}
}
···
}
func (rp *Issues) RepoIssues(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoIssues")
+
params := r.URL.Query()
state := params.Get("state")
isOpen := true
···
page, ok := r.Context().Value("page").(pagination.Page)
if !ok {
-
log.Println("failed to get page")
+
l.Error("failed to get page")
page = pagination.FirstPage()
}
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
db.FilterEq("open", openVal),
)
if err != nil {
-
log.Println("failed to get issues", err)
+
l.Error("failed to get issues", "err", err)
rp.pages.Notice(w, "issues", "Failed to load issues. Try again later.")
return
}
···
db.FilterContains("scope", tangled.RepoIssueNSID),
)
if err != nil {
-
log.Println("failed to fetch labels", err)
+
l.Error("failed to fetch labels", "err", err)
rp.pages.Error503(w)
return
}
···
err = db.PutIssue(tx, issue)
if err != nil {
-
log.Println("failed to create issue", err)
+
l.Error("failed to create issue", "err", err)
rp.pages.Notice(w, "issues", "Failed to create issue.")
return
}
if err = tx.Commit(); err != nil {
-
log.Println("failed to create issue", err)
+
l.Error("failed to create issue", "err", err)
rp.pages.Notice(w, "issues", "Failed to create issue.")
return
}
+1 -3
appview/labels/labels.go
···
"tangled.org/core/appview/oauth"
"tangled.org/core/appview/pages"
"tangled.org/core/appview/validator"
-
"tangled.org/core/log"
"tangled.org/core/rbac"
"tangled.org/core/tid"
···
db *db.DB,
validator *validator.Validator,
enforcer *rbac.Enforcer,
+
logger *slog.Logger,
) *Labels {
-
logger := log.New("labels")
-
return &Labels{
oauth: oauth,
pages: pages,
+15 -12
appview/notifications/notifications.go
···
package notifications
import (
-
"log"
+
"log/slog"
"net/http"
"strconv"
···
)
type Notifications struct {
-
db *db.DB
-
oauth *oauth.OAuth
-
pages *pages.Pages
+
db *db.DB
+
oauth *oauth.OAuth
+
pages *pages.Pages
+
logger *slog.Logger
}
-
func New(database *db.DB, oauthHandler *oauth.OAuth, pagesHandler *pages.Pages) *Notifications {
+
func New(database *db.DB, oauthHandler *oauth.OAuth, pagesHandler *pages.Pages, logger *slog.Logger) *Notifications {
return &Notifications{
-
db: database,
-
oauth: oauthHandler,
-
pages: pagesHandler,
+
db: database,
+
oauth: oauthHandler,
+
pages: pagesHandler,
+
logger: logger,
}
}
···
}
func (n *Notifications) notificationsPage(w http.ResponseWriter, r *http.Request) {
+
l := n.logger.With("handler", "notificationsPage")
user := n.oauth.GetUser(r)
page, ok := r.Context().Value("page").(pagination.Page)
if !ok {
-
log.Println("failed to get page")
+
l.Error("failed to get page")
page = pagination.FirstPage()
}
···
db.FilterEq("recipient_did", user.Did),
)
if err != nil {
-
log.Println("failed to get total notifications:", err)
+
l.Error("failed to get total notifications", "err", err)
n.pages.Error500(w)
return
}
···
db.FilterEq("recipient_did", user.Did),
)
if err != nil {
-
log.Println("failed to get notifications:", err)
+
l.Error("failed to get notifications", "err", err)
n.pages.Error500(w)
return
}
err = n.db.MarkAllNotificationsRead(r.Context(), user.Did)
if err != nil {
-
log.Println("failed to mark notifications as read:", err)
+
l.Error("failed to mark notifications as read", "err", err)
}
unreadCount := 0
+2 -2
appview/pages/pages.go
···
logger *slog.Logger
}
-
func NewPages(config *config.Config, res *idresolver.Resolver) *Pages {
+
func NewPages(config *config.Config, res *idresolver.Resolver, logger *slog.Logger) *Pages {
// initialized with safe defaults, can be overriden per use
rctx := &markup.RenderContext{
IsDev: config.Core.Dev,
···
rctx: rctx,
resolver: res,
templateDir: "appview/pages",
-
logger: slog.Default().With("component", "pages"),
+
logger: logger,
}
if p.dev {
+1 -3
appview/pipelines/pipelines.go
···
"tangled.org/core/appview/reporesolver"
"tangled.org/core/eventconsumer"
"tangled.org/core/idresolver"
-
"tangled.org/core/log"
"tangled.org/core/rbac"
spindlemodel "tangled.org/core/spindle/models"
···
db *db.DB,
config *config.Config,
enforcer *rbac.Enforcer,
+
logger *slog.Logger,
) *Pipelines {
-
logger := log.New("pipelines")
-
return &Pipelines{
oauth: oauth,
repoResolver: repoResolver,
+4
appview/pulls/pulls.go
···
"errors"
"fmt"
"log"
+
"log/slog"
"net/http"
"slices"
"sort"
···
config *config.Config
notifier notify.Notifier
enforcer *rbac.Enforcer
+
logger *slog.Logger
}
func New(
···
config *config.Config,
notifier notify.Notifier,
enforcer *rbac.Enforcer,
+
logger *slog.Logger,
) *Pulls {
return &Pulls{
oauth: oauth,
···
config: config,
notifier: notifier,
enforcer: enforcer,
+
logger: logger,
}
}
+14 -11
appview/repo/index.go
···
import (
"errors"
"fmt"
-
"log"
+
"log/slog"
"net/http"
"net/url"
"slices"
···
)
func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoIndex")
+
ref := chi.URLParam(r, "ref")
ref, _ = url.PathUnescape(ref)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to fully resolve repo", err)
+
l.Error("failed to fully resolve repo", "err", err)
return
}
···
result, err := rp.buildIndexResponse(r.Context(), xrpcc, f, ref)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
if errors.Is(xrpcerr, xrpcclient.ErrXrpcUnsupported) {
-
log.Println("failed to call XRPC repo.index", err)
+
l.Error("failed to call XRPC repo.index", "err", err)
rp.pages.RepoIndexPage(w, pages.RepoIndexParams{
LoggedInUser: user,
NeedsKnotUpgrade: true,
···
}
rp.pages.Error503(w)
-
log.Println("failed to build index response", err)
+
l.Error("failed to build index response", "err", err)
return
}
···
emails := uniqueEmails(commitsTrunc)
emailToDidMap, err := db.GetEmailToDid(rp.db, emails, true)
if err != nil {
-
log.Println("failed to get email to did map", err)
+
l.Error("failed to get email to did map", "err", err)
}
vc, err := commitverify.GetVerifiedObjectCommits(rp.db, emailToDidMap, commitsTrunc)
if err != nil {
-
log.Println(err)
+
l.Error("failed to GetVerifiedObjectCommits", "err", err)
}
// TODO: a bit dirty
-
languageInfo, err := rp.getLanguageInfo(r.Context(), f, xrpcc, result.Ref, ref == "")
+
languageInfo, err := rp.getLanguageInfo(r.Context(), l, f, xrpcc, result.Ref, ref == "")
if err != nil {
-
log.Printf("failed to compute language percentages: %s", err)
+
l.Warn("failed to compute language percentages", "err", err)
// non-fatal
}
···
}
pipelines, err := getPipelineStatuses(rp.db, repoInfo, shas)
if err != nil {
-
log.Printf("failed to fetch pipeline statuses: %s", err)
+
l.Error("failed to fetch pipeline statuses", "err", err)
// non-fatal
}
···
func (rp *Repo) getLanguageInfo(
ctx context.Context,
+
l *slog.Logger,
f *reporesolver.ResolvedRepo,
xrpcc *indigoxrpc.Client,
currentRef string,
···
ls, err := tangled.RepoLanguages(ctx, xrpcc, currentRef, repo)
if err != nil {
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.languages", xrpcerr)
+
l.Error("failed to call XRPC repo.languages", "err", xrpcerr)
return nil, xrpcerr
}
return nil, err
···
err = db.UpdateRepoLanguages(tx, f.RepoAt(), currentRef, langs)
if err != nil {
// non-fatal
-
log.Println("failed to cache lang results", err)
+
l.Error("failed to cache lang results", "err", err)
}
err = tx.Commit()
+130 -92
appview/repo/repo.go
···
"errors"
"fmt"
"io"
-
"log"
"log/slog"
"net/http"
"net/url"
···
}
func (rp *Repo) DownloadArchive(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "DownloadArchive")
+
ref := chi.URLParam(r, "ref")
ref, _ = url.PathUnescape(ref)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", ref, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.archive", xrpcerr)
+
l.Error("failed to call XRPC repo.archive", "err", xrpcerr)
rp.pages.Error503(w)
return
}
···
}
func (rp *Repo) RepoLog(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoLog")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to fully resolve repo", err)
+
l.Error("failed to fully resolve repo", "err", err)
return
}
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
xrpcBytes, err := tangled.RepoLog(r.Context(), xrpcc, cursor, limit, "", ref, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.log", xrpcerr)
+
l.Error("failed to call XRPC repo.log", "err", xrpcerr)
rp.pages.Error503(w)
return
}
var xrpcResp types.RepoLogResponse
if err := json.Unmarshal(xrpcBytes, &xrpcResp); err != nil {
-
log.Println("failed to decode XRPC response", err)
+
l.Error("failed to decode XRPC response", "err", err)
rp.pages.Error503(w)
return
}
tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.tags", xrpcerr)
+
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
rp.pages.Error503(w)
return
}
···
branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.branches", xrpcerr)
+
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
rp.pages.Error503(w)
return
}
···
emailToDidMap, err := db.GetEmailToDid(rp.db, uniqueEmails(xrpcResp.Commits), true)
if err != nil {
-
log.Println("failed to fetch email to did mapping", err)
+
l.Error("failed to fetch email to did mapping", "err", err)
}
vc, err := commitverify.GetVerifiedObjectCommits(rp.db, emailToDidMap, xrpcResp.Commits)
if err != nil {
-
log.Println(err)
+
l.Error("failed to GetVerifiedObjectCommits", "err", err)
}
repoInfo := f.RepoInfo(user)
···
}
pipelines, err := getPipelineStatuses(rp.db, repoInfo, shas)
if err != nil {
-
log.Println(err)
+
l.Error("failed to getPipelineStatuses", "err", err)
// non-fatal
}
···
}
func (rp *Repo) RepoDescriptionEdit(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoDescriptionEdit")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
w.WriteHeader(http.StatusBadRequest)
return
}
···
}
func (rp *Repo) RepoDescription(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoDescription")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
w.WriteHeader(http.StatusBadRequest)
return
}
···
repoAt := f.RepoAt()
rkey := repoAt.RecordKey().String()
if rkey == "" {
-
log.Println("invalid aturi for repo", err)
+
l.Error("invalid aturi for repo", "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
···
newDescription := r.FormValue("description")
client, err := rp.oauth.AuthorizedClient(r)
if err != nil {
-
log.Println("failed to get client")
+
l.Error("failed to get client")
rp.pages.Notice(w, "repo-notice", "Failed to update description, try again later.")
return
}
···
// optimistic update
err = db.UpdateDescription(rp.db, string(repoAt), newDescription)
if err != nil {
-
log.Println("failed to perferom update-description query", err)
+
l.Error("failed to perform update-description query", "err", err)
rp.pages.Notice(w, "repo-notice", "Failed to update description, try again later.")
return
}
···
})
if err != nil {
-
log.Println("failed to perferom update-description query", err)
+
l.Error("failed to perferom update-description query", "err", err)
// failed to get record
rp.pages.Notice(w, "repo-notice", "Failed to update description, unable to save to PDS.")
return
···
}
func (rp *Repo) RepoCommit(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoCommit")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to fully resolve repo", err)
+
l.Error("failed to fully resolve repo", "err", err)
return
}
ref := chi.URLParam(r, "ref")
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
xrpcBytes, err := tangled.RepoDiff(r.Context(), xrpcc, ref, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.diff", xrpcerr)
+
l.Error("failed to call XRPC repo.diff", "err", xrpcerr)
rp.pages.Error503(w)
return
}
var result types.RepoCommitResponse
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
-
log.Println("failed to decode XRPC response", err)
+
l.Error("failed to decode XRPC response", "err", err)
rp.pages.Error503(w)
return
}
emailToDidMap, err := db.GetEmailToDid(rp.db, []string{result.Diff.Commit.Committer.Email, result.Diff.Commit.Author.Email}, true)
if err != nil {
-
log.Println("failed to get email to did mapping:", err)
+
l.Error("failed to get email to did mapping", "err", err)
}
vc, err := commitverify.GetVerifiedCommits(rp.db, emailToDidMap, []types.NiceDiff{*result.Diff})
if err != nil {
-
log.Println(err)
+
l.Error("failed to GetVerifiedCommits", "err", err)
}
user := rp.oauth.GetUser(r)
repoInfo := f.RepoInfo(user)
pipelines, err := getPipelineStatuses(rp.db, repoInfo, []string{result.Diff.Commit.This})
if err != nil {
-
log.Println(err)
+
l.Error("failed to getPipelineStatuses", "err", err)
// non-fatal
}
var pipeline *models.Pipeline
···
}
func (rp *Repo) RepoTree(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoTree")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to fully resolve repo", err)
+
l.Error("failed to fully resolve repo", "err", err)
return
}
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
xrpcResp, err := tangled.RepoTree(r.Context(), xrpcc, treePath, ref, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.tree", xrpcerr)
+
l.Error("failed to call XRPC repo.tree", "err", xrpcerr)
rp.pages.Error503(w)
return
}
···
}
func (rp *Repo) RepoTags(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoTags")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
xrpcBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.tags", xrpcerr)
+
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
rp.pages.Error503(w)
return
}
var result types.RepoTagsResponse
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
-
log.Println("failed to decode XRPC response", err)
+
l.Error("failed to decode XRPC response", "err", err)
rp.pages.Error503(w)
return
}
artifacts, err := db.GetArtifact(rp.db, db.FilterEq("repo_at", f.RepoAt()))
if err != nil {
-
log.Println("failed grab artifacts", err)
+
l.Error("failed grab artifacts", "err", err)
return
}
···
}
func (rp *Repo) RepoBranches(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoBranches")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.branches", xrpcerr)
+
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
rp.pages.Error503(w)
return
}
var result types.RepoBranchesResponse
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
-
log.Println("failed to decode XRPC response", err)
+
l.Error("failed to decode XRPC response", "err", err)
rp.pages.Error503(w)
return
}
···
}
func (rp *Repo) DeleteBranch(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "DeleteBranch")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
noticeId := "delete-branch-error"
fail := func(msg string, err error) {
-
log.Println(msg, "err", err)
+
l.Error(msg, "err", err)
rp.pages.Notice(w, noticeId, msg)
}
···
fail(fmt.Sprintf("Failed to delete branch: %s", err), err)
return
}
-
log.Println("deleted branch from knot", "branch", branch, "repo", f.RepoAt())
+
l.Error("deleted branch from knot", "branch", branch, "repo", f.RepoAt())
rp.pages.HxRefresh(w)
}
func (rp *Repo) RepoBlob(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoBlob")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
}
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Repo.Name)
resp, err := tangled.RepoBlob(r.Context(), xrpcc, filePath, false, ref, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.blob", xrpcerr)
+
l.Error("failed to call XRPC repo.blob", "err", xrpcerr)
rp.pages.Error503(w)
return
}
···
}
func (rp *Repo) RepoBlobRaw(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoBlobRaw")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", err)
w.WriteHeader(http.StatusBadRequest)
return
}
···
req, err := http.NewRequest("GET", blobURL, nil)
if err != nil {
-
log.Println("failed to create request", err)
+
l.Error("failed to create request", "err", err)
return
}
···
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
-
log.Println("failed to reach knotserver", err)
+
l.Error("failed to reach knotserver", "err", err)
rp.pages.Error503(w)
return
}
···
}
if resp.StatusCode != http.StatusOK {
-
log.Printf("knotserver returned non-OK status for raw blob %s: %d", blobURL, resp.StatusCode)
+
l.Error("knotserver returned non-OK status for raw blob", "url", blobURL, "statuscode", resp.StatusCode)
w.WriteHeader(resp.StatusCode)
_, _ = io.Copy(w, resp.Body)
return
···
contentType := resp.Header.Get("Content-Type")
body, err := io.ReadAll(resp.Body)
if err != nil {
-
log.Printf("error reading response body from knotserver: %v", err)
+
l.Error("error reading response body from knotserver", "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
···
db.FilterContains("scope", subject.Collection().String()),
if err != nil {
-
log.Println("failed to fetch label defs", err)
+
l.Error("failed to fetch label defs", "err", err)
return
···
states, err := db.GetLabels(rp.db, db.FilterEq("subject", subject))
if err != nil {
-
log.Println("failed to build label state", err)
+
l.Error("failed to build label state", "err", err)
return
state := states[subject]
···
db.FilterContains("scope", subject.Collection().String()),
if err != nil {
-
log.Println("failed to fetch labels", err)
+
l.Error("failed to fetch labels", "err", err)
return
···
states, err := db.GetLabels(rp.db, db.FilterEq("subject", subject))
if err != nil {
-
log.Println("failed to build label state", err)
+
l.Error("failed to build label state", "err", err)
return
state := states[subject]
···
func (rp *Repo) DeleteRepo(w http.ResponseWriter, r *http.Request) {
user := rp.oauth.GetUser(r)
+
l := rp.logger.With("handler", "DeleteRepo")
noticeId := "operation-error"
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
// remove record from pds
atpClient, err := rp.oauth.AuthorizedClient(r)
if err != nil {
-
log.Println("failed to get authorized client", err)
+
l.Error("failed to get authorized client", "err", err)
return
_, err = comatproto.RepoDeleteRecord(r.Context(), atpClient, &comatproto.RepoDeleteRecord_Input{
···
Rkey: f.Rkey,
})
if err != nil {
-
log.Printf("failed to delete record: %s", err)
+
l.Error("failed to delete record", "err", err)
rp.pages.Notice(w, noticeId, "Failed to delete repository from PDS.")
return
-
log.Println("removed repo record ", f.RepoAt().String())
+
l.Info("removed repo record", "aturi", f.RepoAt().String())
client, err := rp.oauth.ServiceClient(
r,
···
oauth.WithDev(rp.config.Core.Dev),
if err != nil {
-
log.Println("failed to connect to knot server:", err)
+
l.Error("failed to connect to knot server", "err", err)
return
···
rp.pages.Notice(w, noticeId, err.Error())
return
-
log.Println("deleted repo from knot")
+
l.Info("deleted repo from knot")
tx, err := rp.db.BeginTx(r.Context(), nil)
if err != nil {
-
log.Println("failed to start tx")
+
l.Error("failed to start tx")
w.Write(fmt.Append(nil, "failed to add collaborator: ", err))
return
···
tx.Rollback()
err = rp.enforcer.E.LoadPolicy()
if err != nil {
-
log.Println("failed to rollback policies")
+
l.Error("failed to rollback policies")
}()
···
did := c[0]
rp.enforcer.RemoveCollaborator(did, f.Knot, f.DidSlashRepo())
-
log.Println("removed collaborators")
+
l.Info("removed collaborators")
// remove repo RBAC
err = rp.enforcer.RemoveRepo(f.OwnerDid(), f.Knot, f.DidSlashRepo())
···
rp.pages.Notice(w, noticeId, "Failed to update appview")
return
-
log.Println("removed repo from db")
+
l.Info("removed repo from db")
err = tx.Commit()
if err != nil {
-
log.Println("failed to commit changes", err)
+
l.Error("failed to commit changes", "err", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
err = rp.enforcer.E.SavePolicy()
if err != nil {
-
log.Println("failed to update ACLs", err)
+
l.Error("failed to update ACLs", "err", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
···
func (rp *Repo) SetDefaultBranch(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "SetDefaultBranch")
+
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
···
oauth.WithDev(rp.config.Core.Dev),
if err != nil {
-
log.Println("failed to connect to knot server:", err)
+
l.Error("failed to connect to knot server", "err", err)
rp.pages.Notice(w, noticeId, "Failed to connect to knot server.")
return
···
},
if err := xrpcclient.HandleXrpcErr(xe); err != nil {
-
log.Println("xrpc failed", "err", xe)
+
l.Error("xrpc failed", "err", xe)
rp.pages.Notice(w, noticeId, err.Error())
return
···
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
if f.Spindle == "" {
-
log.Println("empty spindle cannot add/rm secret", err)
+
l.Error("empty spindle cannot add/rm secret", "err", err)
return
···
oauth.WithDev(rp.config.Core.Dev),
if err != nil {
-
log.Println("failed to create spindle client", err)
+
l.Error("failed to create spindle client", "err", err)
return
···
func (rp *Repo) generalSettings(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "generalSettings")
+
f, err := rp.repoResolver.Resolve(r)
user := rp.oauth.GetUser(r)
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.branches", xrpcerr)
+
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
rp.pages.Error503(w)
return
var result types.RepoBranchesResponse
if err := json.Unmarshal(xrpcBytes, &result); err != nil {
-
log.Println("failed to decode XRPC response", err)
+
l.Error("failed to decode XRPC response", "err", err)
rp.pages.Error503(w)
return
defaultLabels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", models.DefaultLabelDefs()))
if err != nil {
-
log.Println("failed to fetch labels", err)
+
l.Error("failed to fetch labels", "err", err)
rp.pages.Error503(w)
return
labels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", f.Repo.Labels))
if err != nil {
-
log.Println("failed to fetch labels", err)
+
l.Error("failed to fetch labels", "err", err)
rp.pages.Error503(w)
return
···
func (rp *Repo) accessSettings(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "accessSettings")
+
f, err := rp.repoResolver.Resolve(r)
user := rp.oauth.GetUser(r)
repoCollaborators, err := f.Collaborators(r.Context())
if err != nil {
-
log.Println("failed to get collaborators", err)
+
l.Error("failed to get collaborators", "err", err)
rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{
···
func (rp *Repo) pipelineSettings(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "pipelineSettings")
+
f, err := rp.repoResolver.Resolve(r)
user := rp.oauth.GetUser(r)
// all spindles that the repo owner is a member of
spindles, err := rp.enforcer.GetSpindlesForUser(f.OwnerDid())
if err != nil {
-
log.Println("failed to fetch spindles", err)
+
l.Error("failed to fetch spindles", "err", err)
return
···
oauth.WithExp(60),
oauth.WithDev(rp.config.Core.Dev),
); err != nil {
-
log.Println("failed to create spindle client", err)
+
l.Error("failed to create spindle client", "err", err)
} else if resp, err := tangled.RepoListSecrets(r.Context(), spindleClient, f.RepoAt().String()); err != nil {
-
log.Println("failed to fetch secrets", err)
+
l.Error("failed to fetch secrets", "err", err)
} else {
secrets = resp.Secrets
···
func (rp *Repo) SyncRepoFork(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "SyncRepoFork")
+
ref := chi.URLParam(r, "ref")
ref, _ = url.PathUnescape(ref)
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Printf("failed to resolve source repo: %v", err)
+
l.Error("failed to resolve source repo", "err", err)
return
···
func (rp *Repo) ForkRepo(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "ForkRepo")
+
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Printf("failed to resolve source repo: %v", err)
+
l.Error("failed to resolve source repo", "err", err)
return
···
if err != nil {
if !errors.Is(err, sql.ErrNoRows) {
-
log.Println("error fetching existing repo from db", "err", err)
+
l.Error("error fetching existing repo from db", "err", err)
rp.pages.Notice(w, "repo", "Failed to fork this repository. Try again later.")
return
···
err = db.AddRepo(tx, repo)
if err != nil {
-
log.Println(err)
+
l.Error("failed to AddRepo", "err", err)
rp.pages.Notice(w, "repo", "Failed to save repository information.")
return
···
p, _ := securejoin.SecureJoin(user.Did, forkName)
err = rp.enforcer.AddRepo(user.Did, targetKnot, p)
if err != nil {
-
log.Println(err)
+
l.Error("failed to add ACLs", "err", err)
rp.pages.Notice(w, "repo", "Failed to set up repository permissions.")
return
err = tx.Commit()
if err != nil {
-
log.Println("failed to commit changes", err)
+
l.Error("failed to commit changes", "err", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
err = rp.enforcer.E.SavePolicy()
if err != nil {
-
log.Println("failed to update ACLs", err)
+
l.Error("failed to update ACLs", "err", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
···
func (rp *Repo) RepoCompareNew(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoCompareNew")
+
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
···
repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.branches", xrpcerr)
+
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
rp.pages.Error503(w)
return
var branchResult types.RepoBranchesResponse
if err := json.Unmarshal(branchBytes, &branchResult); err != nil {
-
log.Println("failed to decode XRPC branches response", err)
+
l.Error("failed to decode XRPC branches response", "err", err)
rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
return
···
tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.tags", xrpcerr)
+
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
rp.pages.Error503(w)
return
var tags types.RepoTagsResponse
if err := json.Unmarshal(tagBytes, &tags); err != nil {
-
log.Println("failed to decode XRPC tags response", err)
+
l.Error("failed to decode XRPC tags response", "err", err)
rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
return
···
func (rp *Repo) RepoCompare(w http.ResponseWriter, r *http.Request) {
+
l := rp.logger.With("handler", "RepoCompare")
+
user := rp.oauth.GetUser(r)
f, err := rp.repoResolver.Resolve(r)
if err != nil {
-
log.Println("failed to get repo and knot", err)
+
l.Error("failed to get repo and knot", "err", err)
return
···
head, _ = url.PathUnescape(head)
if base == "" || head == "" {
-
log.Printf("invalid comparison")
+
l.Error("invalid comparison")
rp.pages.Error404(w)
return
···
branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.branches", xrpcerr)
+
l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
rp.pages.Error503(w)
return
var branches types.RepoBranchesResponse
if err := json.Unmarshal(branchBytes, &branches); err != nil {
-
log.Println("failed to decode XRPC branches response", err)
+
l.Error("failed to decode XRPC branches response", "err", err)
rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
return
tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.tags", xrpcerr)
+
l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
rp.pages.Error503(w)
return
var tags types.RepoTagsResponse
if err := json.Unmarshal(tagBytes, &tags); err != nil {
-
log.Println("failed to decode XRPC tags response", err)
+
l.Error("failed to decode XRPC tags response", "err", err)
rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
return
compareBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo, base, head)
if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
-
log.Println("failed to call XRPC repo.compare", xrpcerr)
+
l.Error("failed to call XRPC repo.compare", "err", xrpcerr)
rp.pages.Error503(w)
return
var formatPatch types.RepoFormatPatchResponse
if err := json.Unmarshal(compareBytes, &formatPatch); err != nil {
-
log.Println("failed to decode XRPC compare response", err)
+
l.Error("failed to decode XRPC compare response", "err", err)
rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
return
+1 -1
appview/signup/signup.go
···
disallowed := make(map[string]bool)
if filepath == "" {
-
logger.Debug("no disallowed nicknames file configured")
+
logger.Warn("no disallowed nicknames file configured")
return disallowed
}
+3 -1
appview/state/knotstream.go
···
)
func Knotstream(ctx context.Context, c *config.Config, d *db.DB, enforcer *rbac.Enforcer, posthog posthog.Client) (*ec.Consumer, error) {
+
logger := log.FromContext(ctx)
+
logger = log.SubLogger(logger, "knotstream")
+
knots, err := db.GetRegistrations(
d,
db.FilterIsNot("registered", "null"),
···
srcs[s] = struct{}{}
}
-
logger := log.New("knotstream")
cache := cache.New(c.Redis.Addr)
cursorStore := cursor.NewRedisCursorStore(cache)
+59 -13
appview/state/router.go
···
}
func (s *State) SpindlesRouter() http.Handler {
-
logger := log.New("spindles")
+
logger := log.SubLogger(s.logger, "spindles")
spindles := &spindles.Spindles{
Db: s.db,
···
}
func (s *State) KnotsRouter() http.Handler {
-
logger := log.New("knots")
+
logger := log.SubLogger(s.logger, "knots")
knots := &knots.Knots{
Db: s.db,
···
}
func (s *State) StringsRouter(mw *middleware.Middleware) http.Handler {
-
logger := log.New("strings")
+
logger := log.SubLogger(s.logger, "strings")
strs := &avstrings.Strings{
Db: s.db,
···
}
func (s *State) IssuesRouter(mw *middleware.Middleware) http.Handler {
-
issues := issues.New(s.oauth, s.repoResolver, s.pages, s.idResolver, s.db, s.config, s.notifier, s.validator)
+
issues := issues.New(
+
s.oauth,
+
s.repoResolver,
+
s.pages,
+
s.idResolver,
+
s.db,
+
s.config,
+
s.notifier,
+
s.validator,
+
log.SubLogger(s.logger, "issues"),
+
)
return issues.Router(mw)
}
func (s *State) PullsRouter(mw *middleware.Middleware) http.Handler {
-
pulls := pulls.New(s.oauth, s.repoResolver, s.pages, s.idResolver, s.db, s.config, s.notifier, s.enforcer)
+
pulls := pulls.New(
+
s.oauth,
+
s.repoResolver,
+
s.pages,
+
s.idResolver,
+
s.db,
+
s.config,
+
s.notifier,
+
s.enforcer,
+
log.SubLogger(s.logger, "pulls"),
+
)
return pulls.Router(mw)
}
func (s *State) RepoRouter(mw *middleware.Middleware) http.Handler {
-
logger := log.New("repo")
-
repo := repo.New(s.oauth, s.repoResolver, s.pages, s.spindlestream, s.idResolver, s.db, s.config, s.notifier, s.enforcer, logger, s.validator)
+
repo := repo.New(
+
s.oauth,
+
s.repoResolver,
+
s.pages,
+
s.spindlestream,
+
s.idResolver,
+
s.db,
+
s.config,
+
s.notifier,
+
s.enforcer,
+
log.SubLogger(s.logger, "repo"),
+
s.validator,
+
)
return repo.Router(mw)
}
func (s *State) PipelinesRouter(mw *middleware.Middleware) http.Handler {
-
pipes := pipelines.New(s.oauth, s.repoResolver, s.pages, s.spindlestream, s.idResolver, s.db, s.config, s.enforcer)
+
pipes := pipelines.New(
+
s.oauth,
+
s.repoResolver,
+
s.pages,
+
s.spindlestream,
+
s.idResolver,
+
s.db,
+
s.config,
+
s.enforcer,
+
log.SubLogger(s.logger, "pipelines"),
+
)
return pipes.Router(mw)
}
func (s *State) LabelsRouter(mw *middleware.Middleware) http.Handler {
-
ls := labels.New(s.oauth, s.pages, s.db, s.validator, s.enforcer)
+
ls := labels.New(
+
s.oauth,
+
s.pages,
+
s.db,
+
s.validator,
+
s.enforcer,
+
log.SubLogger(s.logger, "labels"),
+
)
return ls.Router(mw)
}
func (s *State) NotificationsRouter(mw *middleware.Middleware) http.Handler {
-
notifs := notifications.New(s.db, s.oauth, s.pages)
+
notifs := notifications.New(s.db, s.oauth, s.pages, log.SubLogger(s.logger, "notifications"))
return notifs.Router(mw)
}
func (s *State) SignupRouter() http.Handler {
-
logger := log.New("signup")
-
-
sig := signup.New(s.config, s.db, s.posthog, s.idResolver, s.pages, logger)
+
sig := signup.New(s.config, s.db, s.posthog, s.idResolver, s.pages, log.SubLogger(s.logger, "signup"))
return sig.Router()
}
+3 -1
appview/state/spindlestream.go
···
)
func Spindlestream(ctx context.Context, c *config.Config, d *db.DB, enforcer *rbac.Enforcer) (*ec.Consumer, error) {
+
logger := log.FromContext(ctx)
+
logger = log.SubLogger(logger, "spindlestream")
+
spindles, err := db.GetSpindles(
d,
db.FilterIsNot("verified", "null"),
···
srcs[src] = struct{}{}
}
-
logger := log.New("spindlestream")
cache := cache.New(c.Redis.Addr)
cursorStore := cursor.NewRedisCursorStore(cache)
+18 -20
appview/state/state.go
···
"database/sql"
"errors"
"fmt"
-
"log"
"log/slog"
"net/http"
"strings"
···
"tangled.org/core/api/tangled"
"tangled.org/core/appview"
-
"tangled.org/core/appview/cache"
-
"tangled.org/core/appview/cache/session"
"tangled.org/core/appview/config"
"tangled.org/core/appview/db"
"tangled.org/core/appview/models"
···
"tangled.org/core/eventconsumer"
"tangled.org/core/idresolver"
"tangled.org/core/jetstream"
+
"tangled.org/core/log"
tlog "tangled.org/core/log"
"tangled.org/core/rbac"
"tangled.org/core/tid"
···
oauth *oauth.OAuth
enforcer *rbac.Enforcer
pages *pages.Pages
-
sess *session.SessionStore
idResolver *idresolver.Resolver
posthog posthog.Client
jc *jetstream.JetstreamClient
···
}
func Make(ctx context.Context, config *config.Config) (*State, error) {
-
d, err := db.Make(config.Core.DbPath)
+
logger := tlog.FromContext(ctx)
+
+
d, err := db.Make(ctx, config.Core.DbPath)
if err != nil {
return nil, fmt.Errorf("failed to create db: %w", err)
}
···
res, err := idresolver.RedisResolver(config.Redis.ToURL())
if err != nil {
-
log.Printf("failed to create redis resolver: %v", err)
+
logger.Error("failed to create redis resolver", "err", err)
res = idresolver.DefaultResolver()
}
-
pages := pages.NewPages(config, res)
-
cache := cache.New(config.Redis.Addr)
-
sess := session.New(cache)
-
oauth2, err := oauth.New(config)
+
pages := pages.NewPages(config, res, log.SubLogger(logger, "pages"))
+
oauth, err := oauth.New(config)
if err != nil {
return nil, fmt.Errorf("failed to start oauth handler: %w", err)
}
validator := validator.New(d, res, enforcer)
-
posthog, err := posthog.NewWithConfig(config.Posthog.ApiKey, posthog.Config{Endpoint: config.Posthog.Endpoint})
+
posthog, err := posthog.NewWithConfig(config.Posthog.ApiKey, posthog.Config{
+
Endpoint: config.Posthog.Endpoint,
+
})
if err != nil {
return nil, fmt.Errorf("failed to create posthog client: %w", err)
}
···
tangled.LabelOpNSID,
},
nil,
-
slog.Default(),
+
tlog.SubLogger(logger, "jetstream"),
wrapper,
false,
···
Enforcer: enforcer,
IdResolver: res,
Config: config,
-
Logger: tlog.New("ingester"),
+
Logger: log.SubLogger(logger, "ingester"),
Validator: validator,
}
err = jc.StartJetstream(ctx, ingester.Ingest())
···
state := &State{
d,
notifier,
-
oauth2,
+
oauth,
enforcer,
pages,
-
sess,
res,
posthog,
jc,
···
repoResolver,
knotstream,
spindlestream,
-
slog.Default(),
+
logger,
validator,
}
···
}
timeline, err := db.MakeTimeline(s.db, 50, userDid, filtered)
if err != nil {
-
log.Println(err)
+
s.logger.Error("failed to make timeline", "err", err)
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
}
repos, err := db.GetTopStarredReposLastWeek(s.db)
if err != nil {
-
log.Println(err)
+
s.logger.Error("failed to get top starred repos", "err", err)
s.pages.Notice(w, "topstarredrepos", "Unable to load.")
return
}
···
timeline, err := db.MakeTimeline(s.db, 5, "", filtered)
if err != nil {
-
log.Println(err)
+
s.logger.Error("failed to make timeline", "err", err)
s.pages.Notice(w, "timeline", "Uh oh! Failed to load timeline.")
return
}
repos, err := db.GetTopStarredReposLastWeek(s.db)
if err != nil {
-
log.Println(err)
+
s.logger.Error("failed to get top starred repos", "err", err)
s.pages.Notice(w, "topstarredrepos", "Unable to load.")
return
}
+14 -9
cmd/appview/main.go
···
import (
"context"
-
"log"
-
"log/slog"
"net/http"
"os"
"tangled.org/core/appview/config"
"tangled.org/core/appview/state"
+
tlog "tangled.org/core/log"
)
func main() {
-
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, nil)))
-
ctx := context.Background()
+
logger := tlog.New("appview")
+
ctx = tlog.IntoContext(ctx, logger)
c, err := config.LoadConfig(ctx)
if err != nil {
-
log.Println("failed to load config", "error", err)
+
logger.Error("failed to load config", "error", err)
return
}
state, err := state.Make(ctx, c)
defer func() {
-
log.Println(state.Close())
+
if err := state.Close(); err != nil {
+
logger.Error("failed to close state", "err", err)
+
}
}()
if err != nil {
-
log.Fatal(err)
+
logger.Error("failed to start appview", "err", err)
+
os.Exit(-1)
}
-
log.Println("starting server on", c.Core.ListenAddr)
-
log.Println(http.ListenAndServe(c.Core.ListenAddr, state.Router()))
+
logger.Info("starting server", "address", c.Core.ListenAddr)
+
+
if err := http.ListenAndServe(c.Core.ListenAddr, state.Router()); err != nil {
+
logger.Error("failed to start appview", "err", err)
+
}
}
+13
go.mod
···
github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/alecthomas/repr v0.4.0 // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect
github.com/casbin/govaluate v1.3.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
+
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
+
github.com/charmbracelet/lipgloss v1.1.0 // indirect
+
github.com/charmbracelet/log v0.4.2 // indirect
+
github.com/charmbracelet/x/ansi v0.8.0 // indirect
+
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
+
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/cloudflare/circl v1.6.2-0.20250618153321-aa837fd1539d // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
···
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
+
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-redis/cache/v9 v9.0.0 // indirect
···
github.com/lestrrat-go/httprc v1.0.6 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
+
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
+
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
···
github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
+
github.com/muesli/termenv v0.16.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
···
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.64.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
+
github.com/rivo/uniseg v0.4.7 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
···
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wyatt915/treeblood v0.1.15 // indirect
+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
gitlab.com/staticnoise/goldmark-callout v0.0.0-20240609120641-6366b799e4ab // indirect
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
+27
go.sum
···
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk=
github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA=
+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
+
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
···
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
+
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
+
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
+
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
+
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
+
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
+
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
+
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
+
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
+
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
+
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
+
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
···
github.com/go-git/go-git-fixtures/v5 v5.0.0-20241203230421-0753e18f8f03/go.mod h1:hMKrMnUE4W0SJ7bFyM00dyz/HoknZoptGWzrj6M+dEM=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
+
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
+
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
···
github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
+
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
+
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
···
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
+
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
···
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
github.com/resend/resend-go/v2 v2.15.0 h1:B6oMEPf8IEQwn2Ovx/9yymkESLDSeNfLFaNMw+mzHhE=
github.com/resend/resend-go/v2 v2.15.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ=
+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
···
github.com/wyatt915/goldmark-treeblood v0.0.0-20250825231212-5dcbdb2f4b57/go.mod h1:BxSCWByWSRSuembL3cDG1IBUbkBoO/oW/6tF19aA4hs=
github.com/wyatt915/treeblood v0.1.15 h1:3KZ3o2LpcKZAzOLqMoW9qeUzKEaKArKpbcPpTkNfQC8=
github.com/wyatt915/treeblood v0.1.15/go.mod h1:i7+yhhmzdDP17/97pIsOSffw74EK/xk+qJ0029cSXUY=
+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+1 -1
jetstream/jetstream.go
···
sched := sequential.NewScheduler(j.ident, logger, j.withDidFilter(processFunc))
-
client, err := client.NewClient(j.cfg, log.New("jetstream"), sched)
+
client, err := client.NewClient(j.cfg, logger, sched)
if err != nil {
return fmt.Errorf("failed to create jetstream client: %w", err)
}
+39
nix/gomod2nix.toml
···
[mod."github.com/avast/retry-go/v4"]
version = "v4.6.1"
hash = "sha256-PeZc8k4rDV64+k8nZt/oy1YNVbLevltXP3ZD1jf6Z6k="
+
[mod."github.com/aymanbagabas/go-osc52/v2"]
+
version = "v2.0.1"
+
hash = "sha256-6Bp0jBZ6npvsYcKZGHHIUSVSTAMEyieweAX2YAKDjjg="
[mod."github.com/aymerick/douceur"]
version = "v0.2.0"
hash = "sha256-NiBX8EfOvLXNiK3pJaZX4N73YgfzdrzRXdiBFe3X3sE="
···
[mod."github.com/cespare/xxhash/v2"]
version = "v2.3.0"
hash = "sha256-7hRlwSR+fos1kx4VZmJ/7snR7zHh8ZFKX+qqqqGcQpY="
+
[mod."github.com/charmbracelet/colorprofile"]
+
version = "v0.2.3-0.20250311203215-f60798e515dc"
+
hash = "sha256-D9E/bMOyLXAUVOHA1/6o3i+vVmLfwIMOWib6sU7A6+Q="
+
[mod."github.com/charmbracelet/lipgloss"]
+
version = "v1.1.0"
+
hash = "sha256-RHsRT2EZ1nDOElxAK+6/DC9XAaGVjDTgPvRh3pyCfY4="
+
[mod."github.com/charmbracelet/log"]
+
version = "v0.4.2"
+
hash = "sha256-3w1PCM/c4JvVEh2d0sMfv4C77Xs1bPa1Ea84zdynC7I="
+
[mod."github.com/charmbracelet/x/ansi"]
+
version = "v0.8.0"
+
hash = "sha256-/YyDkGrULV2BtnNk3ojeSl0nUWQwIfIdW7WJuGbAZas="
+
[mod."github.com/charmbracelet/x/cellbuf"]
+
version = "v0.0.13-0.20250311204145-2c3ea96c31dd"
+
hash = "sha256-XAhCOt8qJ2vR77lH1ez0IVU1/2CaLTq9jSmrHVg5HHU="
+
[mod."github.com/charmbracelet/x/term"]
+
version = "v0.2.1"
+
hash = "sha256-VBkCZLI90PhMasftGw3403IqoV7d3E5WEGAIVrN5xQM="
[mod."github.com/cloudflare/circl"]
version = "v1.6.2-0.20250618153321-aa837fd1539d"
hash = "sha256-0s/i/XmMcuvPQ+qK9OIU5KxwYZyLVXRtdlYvIXRJT3Y="
···
[mod."github.com/go-jose/go-jose/v3"]
version = "v3.0.4"
hash = "sha256-RrLHCu9l6k0XVobdZQJ9Sx/VTQcWjrdLR5BEG7yXTEQ="
+
[mod."github.com/go-logfmt/logfmt"]
+
version = "v0.6.0"
+
hash = "sha256-RtIG2qARd5sT10WQ7F3LR8YJhS8exs+KiuUiVf75bWg="
[mod."github.com/go-logr/logr"]
version = "v1.4.3"
hash = "sha256-Nnp/dEVNMxLp3RSPDHZzGbI8BkSNuZMX0I0cjWKXXLA="
···
[mod."github.com/lestrrat-go/option"]
version = "v1.0.1"
hash = "sha256-jVcIYYVsxElIS/l2akEw32vdEPR8+anR6oeT1FoYULI="
+
[mod."github.com/lucasb-eyer/go-colorful"]
+
version = "v1.2.0"
+
hash = "sha256-Gg9dDJFCTaHrKHRR1SrJgZ8fWieJkybljybkI9x0gyE="
[mod."github.com/mattn/go-isatty"]
version = "v0.0.20"
hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
+
[mod."github.com/mattn/go-runewidth"]
+
version = "v0.0.16"
+
hash = "sha256-NC+ntvwIpqDNmXb7aixcg09il80ygq6JAnW0Gb5b/DQ="
[mod."github.com/mattn/go-sqlite3"]
version = "v1.14.24"
hash = "sha256-taGKFZFQlR5++5b2oZ1dYS3RERKv6yh1gniNWhb4egg="
···
[mod."github.com/mr-tron/base58"]
version = "v1.2.0"
hash = "sha256-8FzMu3kHUbBX10pUdtGf59Ag7BNupx8ZHeUaodR1/Vk="
+
[mod."github.com/muesli/termenv"]
+
version = "v0.16.0"
+
hash = "sha256-hGo275DJlyLtcifSLpWnk8jardOksdeX9lH4lBeE3gI="
[mod."github.com/multiformats/go-base32"]
version = "v0.1.0"
hash = "sha256-O2IM7FB+Y9MkDdZztyQL5F8oEnmON2Yew7XkotQziio="
···
[mod."github.com/resend/resend-go/v2"]
version = "v2.15.0"
hash = "sha256-1lMoxuMLQXaNWFKadS6rpztAKwvIl3/LWMXqw7f5WYg="
+
[mod."github.com/rivo/uniseg"]
+
version = "v0.4.7"
+
hash = "sha256-rDcdNYH6ZD8KouyyiZCUEy8JrjOQoAkxHBhugrfHjFo="
[mod."github.com/ryanuber/go-glob"]
version = "v1.0.0"
hash = "sha256-YkMl1utwUhi3E0sHK23ISpAsPyj4+KeXyXKoFYGXGVY="
···
[mod."github.com/wyatt915/treeblood"]
version = "v0.1.15"
hash = "sha256-hb99exdkoY2Qv8WdDxhwgPXGbEYimUr6wFtPXEvcO9g="
+
[mod."github.com/xo/terminfo"]
+
version = "v0.0.0-20220910002029-abceb7e1c41e"
+
hash = "sha256-GyCDxxMQhXA3Pi/TsWXpA8cX5akEoZV7CFx4RO3rARU="
[mod."github.com/yuin/goldmark"]
version = "v1.7.13"
hash = "sha256-vBCxZrPYPc8x/nvAAv3Au59dCCyfS80Vw3/a9EXK7TE="
+5 -4
xrpc/serviceauth/service_auth.go
···
"github.com/bluesky-social/indigo/atproto/auth"
"tangled.org/core/idresolver"
+
"tangled.org/core/log"
xrpcerr "tangled.org/core/xrpc/errors"
)
···
func NewServiceAuth(logger *slog.Logger, resolver *idresolver.Resolver, audienceDid string) *ServiceAuth {
return &ServiceAuth{
-
logger: logger,
+
logger: log.SubLogger(logger, "serviceauth"),
resolver: resolver,
audienceDid: audienceDid,
}
···
func (sa *ServiceAuth) VerifyServiceAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-
l := sa.logger.With("url", r.URL)
-
token := r.Header.Get("Authorization")
token = strings.TrimPrefix(token, "Bearer ")
···
did, err := s.Validate(r.Context(), token, nil)
if err != nil {
-
l.Error("signature verification failed", "err", err)
+
sa.logger.Error("signature verification failed", "err", err)
writeError(w, xrpcerr.AuthError(err), http.StatusForbidden)
return
}
+
sa.logger.Debug("valid signature", ActorDid, did)
+
r = r.WithContext(
context.WithValue(r.Context(), ActorDid, did),
)