Logging 3rd Party Queries

We need to log all requests and response to the 3rd party services #

We want to store http request and response headers and data in log_logs table

Idea #

Variety of requests and responses #

  • Some services providing direct access to http.Request object
  • Some services providing an sdk without direct access to http.Request
  • We also want to log incoming request / webhooks

Georgy found a great idea on how to use http.Transport field:

The mechanism #

Go’s http.Client executes HTTP requests via its Transport field, which implements http.RoundTripper. RoundTripper has one method: RoundTrip(*http.Request) (*http.Response, error). This is the heart of http.Client.

We need to extend http.Transport which implements RoundTripper and wraps other RoundTripper (normally http.DefaultTransport) with logging functionality.

Proposal one #

Turn on / off logging directly in app layer

app/app.go:

func (app *App) CreateTrade(ctx context.Context, pg PostgresRepository, profileID int, result interface{}) error {
  // some code

  // turn on logging when needed
	app.TurnOnAppLogging(   // pass all required paramters to logging
    ctx,
    app.repo,
  )

  app.dwolla.CreateTrade(ctx, ...)
  app.dwolla.FundTransfer(ctx, ...)

  app.TurnOffAppLogging()  // revert back default transporter
	return nil
}

app/logging.go:

import (
	"net/http"

	"github.com/webdevelop-pro/go-logging/http2db"
)

func (app *App) TurnOnAppLogging(ctx context.Context, pg PostgresRepository) error {
  http.DefaultTransport = http2db.PostgresTransport(ctx, pg)
}

http2db.go:

// similar to 
// https://github.com/motemen/go-loghttp/blob/master/loghttp.go
// but with store to database 
Pros #
  • adapters can turn on / off logging when
  • no need to change anything in adapters
  • no need to pass any additional paramters to adapters to logging (like database connection)
Cons #
  • Need to make changes in app
  • custom code required for incoming wehook requests

Proposal two #

Turn on / off logging directly in adapters layer

adapters/dwolla.go:

func (dwolla Dwolla) TurnOnAppLogging(client *http.Client) {
	d.client.HTTPClient = client
}

func (dwolla Dwolla) CreateTrade(ctx context.Context, pg PostgresRepository, profileID int, result interface{}) error {
	dwolla.TurnOnAppLogging(   // pass all required paramters to logging
    ctx,
    app.repo,
  )

  dwolla.client.CreateTrade(ctx, ...)

  // revert back default transporter
  app.TurnOffAppLogging()  

	return nil
}
Pros #
  • adapters can turn on / off logging when needed
Cons #
  • Need to make changes in adapters
  • Adapters need to have connection to database
  • custom code required for incoming wehook requests

Future ideas #

  • Migrate to enterprice ready solution
  • Collect logs from pods
  • Store logs to different postgres database or in loki