[feature] Add a request ID and include it in logs (#1476)

This adds a lightweight form of tracing to GTS. Each incoming request is
assigned a Request ID which we then pass on and log in all our log
lines. Any function that gets called downstream from an HTTP handler
should now emit a requestID=value pair whenever it logs something.

Co-authored-by: kim <grufwub@gmail.com>
This commit is contained in:
Daenney 2023-02-17 12:02:29 +01:00 committed by GitHub
commit 68e6d08c76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
118 changed files with 813 additions and 591 deletions

View file

@ -146,7 +146,7 @@ func (a *accountDB) getAccount(ctx context.Context, lookup string, dbQuery func(
// Set the account's related avatar
account.AvatarMediaAttachment, err = a.state.DB.GetAttachmentByID(ctx, account.AvatarMediaAttachmentID)
if err != nil {
log.Errorf("error getting account %s avatar: %v", account.ID, err)
log.Errorf(ctx, "error getting account %s avatar: %v", account.ID, err)
}
}
@ -154,7 +154,7 @@ func (a *accountDB) getAccount(ctx context.Context, lookup string, dbQuery func(
// Set the account's related header
account.HeaderMediaAttachment, err = a.state.DB.GetAttachmentByID(ctx, account.HeaderMediaAttachmentID)
if err != nil {
log.Errorf("error getting account %s header: %v", account.ID, err)
log.Errorf(ctx, "error getting account %s header: %v", account.ID, err)
}
}
@ -162,7 +162,7 @@ func (a *accountDB) getAccount(ctx context.Context, lookup string, dbQuery func(
// Set the account's related emojis
account.Emojis, err = a.state.DB.GetEmojisByIDs(ctx, account.EmojiIDs)
if err != nil {
log.Errorf("error getting account %s emojis: %v", account.ID, err)
log.Errorf(ctx, "error getting account %s emojis: %v", account.ID, err)
}
}
@ -412,7 +412,7 @@ func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, li
Where("? != '{}'", bun.Ident("status.attachments")).
Where("? != '[]'", bun.Ident("status.attachments"))
default:
log.Panic("db dialect was neither pg nor sqlite")
log.Panic(ctx, "db dialect was neither pg nor sqlite")
return q
}
})
@ -540,7 +540,7 @@ func (a *accountDB) statusesFromIDs(ctx context.Context, statusIDs []string) ([]
// Fetch from status from database by ID
status, err := a.state.DB.GetStatusByID(ctx, id)
if err != nil {
log.Errorf("statusesFromIDs: error getting status %q: %v", id, err)
log.Errorf(ctx, "error getting status %q: %v", id, err)
continue
}

View file

@ -93,7 +93,7 @@ func (a *adminDB) IsEmailAvailable(ctx context.Context, email string) (bool, db.
func (a *adminDB) NewSignup(ctx context.Context, username string, reason string, requireApproval bool, email string, password string, signUpIP net.IP, locale string, appID string, emailVerified bool, externalID string, admin bool) (*gtsmodel.User, db.Error) {
key, err := rsa.GenerateKey(rand.Reader, rsaKeyBits)
if err != nil {
log.Errorf("error creating new rsa key: %s", err)
log.Errorf(ctx, "error creating new rsa key: %s", err)
return nil, err
}
@ -107,7 +107,7 @@ func (a *adminDB) NewSignup(ctx context.Context, username string, reason string,
Scan(ctx); err != nil {
err = a.conn.ProcessError(err)
if err != db.ErrNoEntries {
log.Errorf("error checking for existing account: %s", err)
log.Errorf(ctx, "error checking for existing account: %s", err)
return nil, err
}
@ -207,13 +207,13 @@ func (a *adminDB) CreateInstanceAccount(ctx context.Context) db.Error {
return err
}
if exists {
log.Infof("instance account %s already exists", username)
log.Infof(ctx, "instance account %s already exists", username)
return nil
}
key, err := rsa.GenerateKey(rand.Reader, rsaKeyBits)
if err != nil {
log.Errorf("error creating new rsa key: %s", err)
log.Errorf(ctx, "error creating new rsa key: %s", err)
return err
}
@ -245,7 +245,7 @@ func (a *adminDB) CreateInstanceAccount(ctx context.Context) db.Error {
return err
}
log.Infof("instance account %s CREATED with id %s", username, acct.ID)
log.Infof(ctx, "instance account %s CREATED with id %s", username, acct.ID)
return nil
}
@ -265,7 +265,7 @@ func (a *adminDB) CreateInstanceInstance(ctx context.Context) db.Error {
return err
}
if exists {
log.Infof("instance entry already exists")
log.Infof(ctx, "instance entry already exists")
return nil
}
@ -290,6 +290,6 @@ func (a *adminDB) CreateInstanceInstance(ctx context.Context) db.Error {
return a.conn.ProcessError(err)
}
log.Infof("created instance instance %s with id %s", host, i.ID)
log.Infof(ctx, "created instance instance %s with id %s", host, i.ID)
return nil
}

View file

@ -165,6 +165,6 @@ func (b *basicDB) IsHealthy(ctx context.Context) db.Error {
}
func (b *basicDB) Stop(ctx context.Context) db.Error {
log.Info("closing db connection")
log.Info(ctx, "closing db connection")
return b.conn.Close()
}

View file

@ -100,11 +100,11 @@ func doMigration(ctx context.Context, db *bun.DB) error {
}
if group.ID == 0 {
log.Info("there are no new migrations to run")
log.Info(ctx, "there are no new migrations to run")
return nil
}
log.Infof("MIGRATED DATABASE TO %s", group)
log.Infof(ctx, "MIGRATED DATABASE TO %s", group)
return nil
}
@ -245,7 +245,7 @@ func pgConn(ctx context.Context) (*DBConn, error) {
return nil, fmt.Errorf("postgres ping: %s", err)
}
log.Info("connected to POSTGRES database")
log.Info(ctx, "connected to POSTGRES database")
return conn, nil
}
@ -268,7 +268,7 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
}
if address == ":memory:" {
log.Warn("using sqlite in-memory mode; all data will be deleted when gts shuts down; this mode should only be used for debugging or running tests")
log.Warn(ctx, "using sqlite in-memory mode; all data will be deleted when gts shuts down; this mode should only be used for debugging or running tests")
// Use random name for in-memory instead of ':memory:', so
// multiple in-mem databases can be created without conflict.
@ -319,7 +319,7 @@ func sqliteConn(ctx context.Context) (*DBConn, error) {
}
return nil, fmt.Errorf("sqlite ping: %s", err)
}
log.Infof("connected to SQLITE database with address %s", address)
log.Infof(ctx, "connected to SQLITE database with address %s", address)
return conn, nil
}
@ -464,7 +464,7 @@ func sqlitePragmas(ctx context.Context, conn *DBConn) error {
return fmt.Errorf("error scanning sqlite pragma %s: %w", pv, err)
}
log.Infof("sqlite pragma %s set to %s", pk, res)
log.Infof(ctx, "sqlite pragma %s set to %s", pk, res)
}
return nil

View file

@ -372,7 +372,7 @@ func (e *emojiDB) GetEmojisByIDs(ctx context.Context, emojiIDs []string) ([]*gts
for _, id := range emojiIDs {
emoji, err := e.GetEmojiByID(ctx, id)
if err != nil {
log.Errorf("emojisFromIDs: error getting emoji %q: %v", id, err)
log.Errorf(ctx, "emojisFromIDs: error getting emoji %q: %v", id, err)
continue
}
@ -405,7 +405,7 @@ func (e *emojiDB) GetEmojiCategoriesByIDs(ctx context.Context, emojiCategoryIDs
for _, id := range emojiCategoryIDs {
emojiCategory, err := e.GetEmojiCategory(ctx, id)
if err != nil {
log.Errorf("emojiCategoriesFromIDs: error getting emoji category %q: %v", id, err)
log.Errorf(ctx, "error getting emoji category %q: %v", id, err)
continue
}

View file

@ -36,17 +36,18 @@ func (queryHook) BeforeQuery(ctx context.Context, _ *bun.QueryEvent) context.Con
}
// AfterQuery logs the time taken to query, the operation (select, update, etc), and the query itself as translated by bun.
func (queryHook) AfterQuery(_ context.Context, event *bun.QueryEvent) {
func (queryHook) AfterQuery(ctx context.Context, event *bun.QueryEvent) {
// Get the DB query duration
dur := time.Since(event.StartTime)
switch {
// Warn on slow database queries
case dur > time.Second:
log.WithFields(kv.Fields{
{"duration", dur},
{"query", event.Query},
}...).Warn("SLOW DATABASE QUERY")
log.WithContext(ctx).
WithFields(kv.Fields{
{"duration", dur},
{"query", event.Query},
}...).Warn("SLOW DATABASE QUERY")
// On trace, we log query information,
// manually crafting so DB query not escaped.

View file

@ -58,7 +58,7 @@ func (m *mediaDB) getAttachments(ctx context.Context, ids []string) ([]*gtsmodel
// Attempt fetch from DB
attachment, err := m.GetAttachmentByID(ctx, id)
if err != nil {
log.Errorf("error getting attachment %q: %v", id, err)
log.Errorf(ctx, "error getting attachment %q: %v", id, err)
continue
}

View file

@ -64,7 +64,7 @@ func (m *mentionDB) GetMentions(ctx context.Context, ids []string) ([]*gtsmodel.
// Attempt fetch from DB
mention, err := m.GetMention(ctx, id)
if err != nil {
log.Errorf("GetMentions: error getting mention %q: %v", id, err)
log.Errorf(ctx, "error getting mention %q: %v", id, err)
continue
}

View file

@ -38,7 +38,7 @@ func init() {
case dialect.SQLite:
q = q.ColumnExpr("? VARCHAR", bun.Ident("emojis"))
default:
log.Panic("db dialect was neither pg nor sqlite")
log.Panic(ctx, "db dialect was neither pg nor sqlite")
}
if _, err := q.Exec(ctx); err != nil {

View file

@ -94,7 +94,7 @@ func (n *notificationDB) GetNotifications(ctx context.Context, accountID string,
// Attempt fetch from DB
notif, err := n.GetNotification(ctx, id)
if err != nil {
log.Errorf("GetNotifications: error getting notification %q: %v", id, err)
log.Errorf(ctx, "error getting notification %q: %v", id, err)
continue
}

View file

@ -106,7 +106,7 @@ func (r *reportDB) GetReports(ctx context.Context, resolved *bool, accountID str
for _, id := range reportIDs {
report, err := r.GetReportByID(ctx, id)
if err != nil {
log.Errorf("GetReports: error getting report %q: %v", id, err)
log.Errorf(ctx, "error getting report %q: %v", id, err)
continue
}

View file

@ -74,7 +74,7 @@ func (s *statusDB) GetStatuses(ctx context.Context, ids []string) ([]*gtsmodel.S
// Attempt fetch from DB
status, err := s.GetStatusByID(ctx, id)
if err != nil {
log.Errorf("GetStatuses: error getting status %q: %v", id, err)
log.Errorf(ctx, "error getting status %q: %v", id, err)
continue
}
@ -387,7 +387,7 @@ func (s *statusDB) GetStatusChildren(ctx context.Context, status *gtsmodel.Statu
// only append children, not the overall parent status
entry, ok := e.Value.(*gtsmodel.Status)
if !ok {
log.Panic("GetStatusChildren: found status could not be asserted to *gtsmodel.Status")
log.Panic(ctx, "found status could not be asserted to *gtsmodel.Status")
}
if entry.ID != status.ID {
@ -412,7 +412,7 @@ func (s *statusDB) statusChildren(ctx context.Context, status *gtsmodel.Status,
if err := q.Scan(ctx, &childIDs); err != nil {
if err != sql.ErrNoRows {
log.Errorf("statusChildren: error getting children for %q: %v", status.ID, err)
log.Errorf(ctx, "error getting children for %q: %v", status.ID, err)
}
return
}
@ -421,7 +421,7 @@ func (s *statusDB) statusChildren(ctx context.Context, status *gtsmodel.Status,
// Fetch child with ID from database
child, err := s.GetStatusByID(ctx, id)
if err != nil {
log.Errorf("statusChildren: error getting child status %q: %v", id, err)
log.Errorf(ctx, "error getting child status %q: %v", id, err)
continue
}
@ -429,7 +429,7 @@ func (s *statusDB) statusChildren(ctx context.Context, status *gtsmodel.Status,
for e := foundStatuses.Front(); e != nil; e = e.Next() {
entry, ok := e.Value.(*gtsmodel.Status)
if !ok {
log.Panic("statusChildren: found status could not be asserted to *gtsmodel.Status")
log.Panic(ctx, "found status could not be asserted to *gtsmodel.Status")
}
if child.InReplyToAccountID != "" && entry.ID == child.InReplyToID {

View file

@ -114,7 +114,7 @@ func (t *timelineDB) GetHomeTimeline(ctx context.Context, accountID string, maxI
// Fetch status from db for ID
status, err := t.state.DB.GetStatusByID(ctx, id)
if err != nil {
log.Errorf("GetHomeTimeline: error fetching status %q: %v", id, err)
log.Errorf(ctx, "error fetching status %q: %v", id, err)
continue
}
@ -182,7 +182,7 @@ func (t *timelineDB) GetPublicTimeline(ctx context.Context, maxID string, sinceI
// Fetch status from db for ID
status, err := t.state.DB.GetStatusByID(ctx, id)
if err != nil {
log.Errorf("GetPublicTimeline: error fetching status %q: %v", id, err)
log.Errorf(ctx, "error fetching status %q: %v", id, err)
continue
}
@ -242,7 +242,7 @@ func (t *timelineDB) GetFavedTimeline(ctx context.Context, accountID string, max
// Fetch status from db for corresponding favourite
status, err := t.state.DB.GetStatusByID(ctx, fave.StatusID)
if err != nil {
log.Errorf("GetFavedTimeline: error fetching status for fave %q: %v", fave.ID, err)
log.Errorf(ctx, "error fetching status for fave %q: %v", fave.ID, err)
continue
}