[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
parent b5993095fa
commit 68e6d08c76
118 changed files with 813 additions and 591 deletions

View File

@@ -59,13 +59,13 @@ func (p *processor) Create(ctx context.Context, applicationToken oauth2.TokenInf
reason = ""
}
log.Trace("creating new username and account")
log.Trace(ctx, "creating new username and account")
user, err := p.db.NewSignup(ctx, form.Username, text.SanitizePlaintext(reason), approvalRequired, form.Email, form.Password, form.IP, form.Locale, application.ID, false, "", false)
if err != nil {
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error creating new signup in the database: %s", err))
}
log.Tracef("generating a token for user %s with account %s and application %s", user.ID, user.AccountID, application.ID)
log.Tracef(ctx, "generating a token for user %s with account %s and application %s", user.ID, user.AccountID, application.ID)
accessToken, err := p.oauthServer.GenerateUserAccessToken(ctx, applicationToken, application.ClientSecret, user.ID)
if err != nil {
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error creating new access token for user %s: %s", user.ID, err))

View File

@@ -64,7 +64,7 @@ func (p *processor) Delete(ctx context.Context, account *gtsmodel.Account, origi
})
}
l := log.WithFields(fields...)
l := log.WithContext(ctx).WithFields(fields...)
l.Trace("beginning account delete process")
// 1. Delete account's application(s), clients, and oauth tokens

View File

@@ -97,7 +97,7 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form
}
account.AvatarMediaAttachmentID = avatarInfo.ID
account.AvatarMediaAttachment = avatarInfo
log.Tracef("new avatar info for account %s is %+v", account.ID, avatarInfo)
log.Tracef(ctx, "new avatar info for account %s is %+v", account.ID, avatarInfo)
}
if form.Header != nil && form.Header.Size != 0 {
@@ -107,7 +107,7 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form
}
account.HeaderMediaAttachmentID = headerInfo.ID
account.HeaderMediaAttachment = headerInfo
log.Tracef("new header info for account %s is %+v", account.ID, headerInfo)
log.Tracef(ctx, "new header info for account %s is %+v", account.ID, headerInfo)
}
if form.Locked != nil {

View File

@@ -89,9 +89,10 @@ func (p *processor) DomainBlockCreate(ctx context.Context, account *gtsmodel.Acc
// 2. Delete the instance account for that instance if it exists.
// 3. Select all accounts from this instance and pass them through the delete functionality of the processor.
func (p *processor) initiateDomainBlockSideEffects(ctx context.Context, account *gtsmodel.Account, block *gtsmodel.DomainBlock) {
l := log.WithFields(kv.Fields{
{"domain", block.Domain},
}...)
l := log.WithContext(ctx).
WithFields(kv.Fields{
{"domain", block.Domain},
}...)
l.Debug("processing domain block side effects")

View File

@@ -35,12 +35,12 @@ func (p *processor) MediaRefetch(ctx context.Context, requestingAccount *gtsmode
}
go func() {
log.Info("starting emoji refetch")
log.Info(ctx, "starting emoji refetch")
refetched, err := p.mediaManager.RefetchEmojis(context.Background(), domain, transport.DereferenceMedia)
if err != nil {
log.Errorf("error refetching emojis: %s", err)
log.Errorf(ctx, "error refetching emojis: %s", err)
} else {
log.Infof("refetched %d emojis from remote", refetched)
log.Infof(ctx, "refetched %d emojis from remote", refetched)
}
}()

View File

@@ -50,7 +50,7 @@ func (p *processor) ProcessFromClientAPI(ctx context.Context, clientMsg messages
}
// Log this federated message
l := log.WithFields(fields...)
l := log.WithContext(ctx).WithFields(fields...)
l.Info("processing from client")
switch clientMsg.APActivityType {

View File

@@ -59,7 +59,7 @@ func (p *processor) ProcessFromFederator(ctx context.Context, federatorMsg messa
}
// Log this federated message
l := log.WithFields(fields...)
l := log.WithContext(ctx).WithFields(fields...)
l.Info("processing from federator")
switch federatorMsg.APActivityType {

View File

@@ -40,7 +40,7 @@ func (p *processor) GetCustomEmojis(ctx context.Context) ([]*apimodel.Emoji, gts
for _, gtsEmoji := range emojis {
apiEmoji, err := p.tc.EmojiToAPIEmoji(ctx, gtsEmoji)
if err != nil {
log.Errorf("error converting emoji with id %s: %s", gtsEmoji.ID, err)
log.Errorf(ctx, "error converting emoji with id %s: %s", gtsEmoji.ID, err)
continue
}
apiEmojis = append(apiEmojis, &apiEmoji)

View File

@@ -46,7 +46,7 @@ func (p *processor) NotificationsGet(ctx context.Context, authed *oauth.Auth, ex
for i, n := range notifs {
item, err := p.tc.NotificationToAPINotification(ctx, n)
if err != nil {
log.Debugf("got an error converting a notification to api, will skip it: %s", err)
log.Debugf(ctx, "got an error converting a notification to api, will skip it: %s", err)
continue
}

View File

@@ -57,7 +57,8 @@ func (p *processor) SearchGet(ctx context.Context, authed *oauth.Auth, search *a
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
l := log.WithFields(kv.Fields{{"query", query}}...)
l := log.WithContext(ctx).
WithFields(kv.Fields{{"query", query}}...)
searchResult := &apimodel.SearchResult{
Accounts: []apimodel.Account{},

View File

@@ -72,7 +72,7 @@ func StatusFilterFunction(database db.DB, filter visibility.Filter) timeline.Fil
timelineable, err := filter.StatusHometimelineable(ctx, status, requestingAccount)
if err != nil {
log.Warnf("error checking hometimelineability of status %s for account %s: %s", status.ID, timelineAccountID, err)
log.Warnf(ctx, "error checking hometimelineability of status %s for account %s: %s", status.ID, timelineAccountID, err)
}
return timelineable, nil // we don't return the error here because we want to just skip this item if something goes wrong
@@ -257,7 +257,7 @@ func (p *processor) filterPublicStatuses(ctx context.Context, authed *oauth.Auth
targetAccount := &gtsmodel.Account{}
if err := p.db.GetByID(ctx, s.AccountID, targetAccount); err != nil {
if err == db.ErrNoEntries {
log.Debugf("filterPublicStatuses: skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
log.Debugf(ctx, "skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
continue
}
return nil, gtserror.NewErrorInternalError(fmt.Errorf("filterPublicStatuses: error getting status author: %s", err))
@@ -265,7 +265,7 @@ func (p *processor) filterPublicStatuses(ctx context.Context, authed *oauth.Auth
timelineable, err := p.filter.StatusPublictimelineable(ctx, s, authed.Account)
if err != nil {
log.Debugf("filterPublicStatuses: skipping status %s because of an error checking status visibility: %s", s.ID, err)
log.Debugf(ctx, "skipping status %s because of an error checking status visibility: %s", s.ID, err)
continue
}
if !timelineable {
@@ -274,7 +274,7 @@ func (p *processor) filterPublicStatuses(ctx context.Context, authed *oauth.Auth
apiStatus, err := p.tc.StatusToAPIStatus(ctx, s, authed.Account)
if err != nil {
log.Debugf("filterPublicStatuses: skipping status %s because it couldn't be converted to its api representation: %s", s.ID, err)
log.Debugf(ctx, "skipping status %s because it couldn't be converted to its api representation: %s", s.ID, err)
continue
}
@@ -290,7 +290,7 @@ func (p *processor) filterFavedStatuses(ctx context.Context, authed *oauth.Auth,
targetAccount := &gtsmodel.Account{}
if err := p.db.GetByID(ctx, s.AccountID, targetAccount); err != nil {
if err == db.ErrNoEntries {
log.Debugf("filterFavedStatuses: skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
log.Debugf(ctx, "skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
continue
}
return nil, gtserror.NewErrorInternalError(fmt.Errorf("filterPublicStatuses: error getting status author: %s", err))
@@ -298,7 +298,7 @@ func (p *processor) filterFavedStatuses(ctx context.Context, authed *oauth.Auth,
timelineable, err := p.filter.StatusVisible(ctx, s, authed.Account)
if err != nil {
log.Debugf("filterFavedStatuses: skipping status %s because of an error checking status visibility: %s", s.ID, err)
log.Debugf(ctx, "skipping status %s because of an error checking status visibility: %s", s.ID, err)
continue
}
if !timelineable {
@@ -307,7 +307,7 @@ func (p *processor) filterFavedStatuses(ctx context.Context, authed *oauth.Auth,
apiStatus, err := p.tc.StatusToAPIStatus(ctx, s, authed.Account)
if err != nil {
log.Debugf("filterFavedStatuses: skipping status %s because it couldn't be converted to its api representation: %s", s.ID, err)
log.Debugf(ctx, "skipping status %s because it couldn't be converted to its api representation: %s", s.ID, err)
continue
}

View File

@@ -32,11 +32,11 @@ import (
)
func (p *processor) OpenStreamForAccount(ctx context.Context, account *gtsmodel.Account, streamTimeline string) (*stream.Stream, gtserror.WithCode) {
l := log.WithFields(kv.Fields{
{"account", account.ID},
{"streamType", streamTimeline},
}...)
l := log.WithContext(ctx).
WithFields(kv.Fields{
{"account", account.ID},
{"streamType", streamTimeline},
}...)
l.Debug("received open stream request")
// each stream needs a unique ID so we know to close it