Repository: moov-io/customers
Pull request #219 (2020-10-05 15:08:15)

Replace go-kit/log with base/log
As part of #120 I'm working on replacing `internal/database` with `base/database` package.
`base/database` depends on `base/log` while inside Customers project we use `go-kit/log`.

With this PR I'm replacing go-kit/log with base/log.

codecov-commenter: # [Codecov](https://codecov.io/gh/moov-io/customers/pull/219?src=pr&el=h1) Report
> Merging [#219](https://codecov.io/gh/moov-io/customers/pull/219?src=pr&el=desc) into [master](https://codecov.io/gh/moov-io/customers/commit/4475e6c005595f07ef170b39e6106885d30862a7?el=desc) will **decrease** coverage by `0.51%`.
> The diff coverage is `30.27%`.


```diff
@@            Coverage Diff             @@
##           master     #219      +/-   ##
==========================================
- Coverage   61.13%   60.61%   -0.52%     
==========================================
  Files          49       50       +1     
  Lines        2722     2745      +23     
==========================================
  Hits         1664     1664              
- Misses        743      766      +23     
  Partials      315      315              
```

adamdecaf: Seems fine. Can we flip the order (log before `.Problem(...)`)
alovak: This comment is just for keeping the history:

I have few questions/concerns:

**First**, Customers project uses `base/http.Wrap` which depends on `go-kit/log` and in order to replace it with `base/log` we may:
1.  replace `go-kit/log` with `base/log`. This will require us to update other packages like Fed, Wire, Watchman. 
2.  extract `Wrap` method and modify it inside our project without touching any dependencies
3. create new method with name like ...`WrapWithBaseLogger`?

**Second**, replacing this:

```go
logger.Log("accounts", fmt.Sprintf("problem saving account: %v", err), "requestID", moovhttp.GetRequestID(r))
```
with this:
```go
logger.WithKeyValue("accounts", fmt.Sprintf("problem saving account: %v", err), "requestID", moovhttp.GetRequestID(r))
```
 
in many places I see that `base/log.Log` (which is main method) accepts one argument and it does not match to how we call it in Customers. In Customers we pass pairs of key values. My following questions:
* should we change `base/log.Log` method to accept key/value pairs?
* should we change what and how we log data in Customers?
  * we don't need requestID as it should be logged by default when we use `Wrap` method
  * how do we use package name keys like "accounts", "customers", "ofac", later from logs?

codecov-io: # [Codecov](https://codecov.io/gh/moov-io/customers/pull/219?src=pr&el=h1) Report
> Merging [#219](https://codecov.io/gh/moov-io/customers/pull/219?src=pr&el=desc) into [master](https://codecov.io/gh/moov-io/customers/commit/4475e6c005595f07ef170b39e6106885d30862a7?el=desc) will **decrease** coverage by `0.47%`.
> The diff coverage is `37.87%`.


```diff
@@            Coverage Diff             @@
##           master     #219      +/-   ##
==========================================
- Coverage   61.13%   60.65%   -0.48%     
==========================================
  Files          49       50       +1     
  Lines        2722     2758      +36     
==========================================
+ Hits         1664     1673       +9     
- Misses        743      771      +28     
+ Partials      315      314       -1     
```


Patch:
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 2b7d898..b490ae6 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -22,6 +22,9 @@ import (
 
 	mainPkg "github.com/moov-io/customers"
 	"github.com/moov-io/customers/internal/database"
+
+	"github.com/moov-io/base/log"
+
 	"github.com/moov-io/customers/internal/util"
 	"github.com/moov-io/customers/pkg/accounts"
 	"github.com/moov-io/customers/pkg/configuration"
@@ -38,7 +41,6 @@ import (
 	"github.com/moov-io/customers/pkg/validator/plaid"
 	"github.com/moov-io/customers/pkg/watchman"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
 	"github.com/mattn/go-sqlite3"
 	"gocloud.dev/blob/fileblob"
@@ -56,14 +58,13 @@ func main() {
 
 	var logger log.Logger
 	if strings.ToLower(*flagLogFormat) == "json" {
-		logger = log.NewJSONLogger(os.Stderr)
+		logger = log.NewJSONLogger()
 	} else {
-		logger = log.NewLogfmtLogger(os.Stderr)
+		logger = log.NewDefaultLogger()
 	}
-	logger = log.With(logger, "ts", log.DefaultTimestampUTC)
-	logger = log.With(logger, "caller", log.DefaultCaller)
 
-	logger.Log("startup", fmt.Sprintf("Starting moov-io/customers server version %s", mainPkg.Version))
+	logger = logger.WithKeyValue("app", "customers")
+	logger.WithKeyValue("phase", "startup").Log(fmt.Sprintf("Starting moov-io/customers server version %s", mainPkg.Version))
 
 	// Channel for errors
 	errs := make(chan error)
@@ -76,18 +77,18 @@ func main() {
 
 	// Setup SQLite database
 	if sqliteVersion, _, _ := sqlite3.Version(); sqliteVersion != "" {
-		logger.Log("main", fmt.Sprintf("sqlite version %s", sqliteVersion))
+		logger.Log(fmt.Sprintf("sqlite version %s", sqliteVersion))
 	}
 
 	// Setup database connection
 	db, err := database.New(logger, os.Getenv("DATABASE_TYPE"))
 	if err != nil {
-		logger.Log("main", err)
+		logger.LogError("failed to connect to database", err)
 		os.Exit(1)
 	}
 	defer func() {
 		if err := db.Close(); err != nil {
-			logger.Log("main", err)
+			logger.LogError("failed to close database connection", err)
 		}
 	}()
 
@@ -102,10 +103,9 @@ func main() {
 	adminServer := admin.NewServer(*adminAddr)
 	adminServer.AddVersionHandler(mainPkg.Version) // Setup 'GET /version'
 	go func() {
-		logger.Log("admin", fmt.Sprintf("listening on %s", adminServer.BindAddr()))
+		logger.Log(fmt.Sprintf("admin listening on %s", adminServer.BindAddr()))
 		if err := adminServer.Listen(); err != nil {
-			err = fmt.Errorf("problem starting admin http: %v", err)
-			logger.Log("admin", err)
+			logger.LogErrorF("problem starting admin http: %v", err)
 			errs <- err
 		}
 	}()
@@ -218,21 +218,21 @@ func main() {
 	}
 	shutdownServer := func() {
 		if err := serve.Shutdown(context.TODO()); err != nil {
-			logger.Log("shutdown", err)
+			logger.WithKeyValue("phase", "shutdown").LogError("failed to shutdown server", err)
 		}
 	}
 
 	// Start business logic HTTP server
 	go func() {
 		if certFile, keyFile := os.Getenv("HTTPS_CERT_FILE"), os.Getenv("HTTPS_KEY_FILE"); certFile != "" && keyFile != "" {
-			logger.Log("startup", fmt.Sprintf("binding to %s for secure HTTP server", *httpAddr))
+			logger.WithKeyValue("phase", "startup").Log(fmt.Sprintf("binding to %s for secure HTTP server", *httpAddr))
 			if err := serve.ListenAndServeTLS(certFile, keyFile); err != nil {
-				logger.Log("exit", err)
+				logger.LogError("failed to start TLS server", err)
 			}
 		} else {
-			logger.Log("startup", fmt.Sprintf("binding to %s for HTTP server", *httpAddr))
+			logger.WithKeyValue("phase", "startup").Log(fmt.Sprintf("binding to %s for HTTP server", *httpAddr))
 			if err := serve.ListenAndServe(); err != nil {
-				logger.Log("exit", err)
+				logger.LogError("failed to start server", err)
 			}
 		}
 	}()
@@ -240,7 +240,7 @@ func main() {
 	// Block/Wait for an error
 	if err := <-errs; err != nil {
 		shutdownServer()
-		logger.Log("exit", err)
+		logger.LogError("service error", err)
 	}
 }
 
@@ -261,7 +261,7 @@ func setupSigner(logger log.Logger, bucketName, cloudProvider string) *fileblob.
 		}
 		if secret == "" {
 			secret = "secret"
-			logger.Log("main", "WARNING!!!! USING INSECURE DEFAULT FILE STORAGE, set FILEBLOB_HMAC_SECRET for ANY production usage")
+			logger.Log("WARNING!!!! USING INSECURE DEFAULT FILE STORAGE, set FILEBLOB_HMAC_SECRET for ANY production usage")
 		}
 		signer, err := storage.FileblobSigner(baseURL, secret)
 		if err != nil {
diff --git a/go.mod b/go.mod
index abd560b..c15b032 100644
--- a/go.mod
+++ b/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/mattn/go-sqlite3 v2.0.3+incompatible
 	github.com/mitchellh/mapstructure v1.3.3
 	github.com/moov-io/ach v1.4.4
-	github.com/moov-io/base v0.11.1
+	github.com/moov-io/base v0.11.2-0.20201003162845-340ece6ad5df
 	github.com/moov-io/fed v0.5.1
 	github.com/moov-io/identity v0.2.7 // indirect
 	github.com/moov-io/paygate v0.8.0
diff --git a/go.sum b/go.sum
index 04f10cf..4fdb81f 100644
--- a/go.sum
+++ b/go.sum
@@ -330,6 +330,7 @@ github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/golang-migrate/migrate/v4 v4.11.0/go.mod h1:nqbpDbckcYjsCD5I8q5+NI9Tkk7SVcmaF40Ax1eAWhg=
+github.com/golang-migrate/migrate/v4 v4.12.2 h1:QI43Tlouiwpp2dK5Y767OouX0snJNRP/NubsVaArzDU=
 github.com/golang-migrate/migrate/v4 v4.12.2/go.mod h1:HQ1DaC8uLHkg4afY8ZQ8D/P5SG+YW9X5INZBVvm+d2k=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
@@ -626,6 +627,8 @@ github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
 github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
 github.com/markbates/pkger v0.17.0 h1:RFfyBPufP2V6cddUyyEVSHBpaAnM1WzaMNyqomeT+iY=
 github.com/markbates/pkger v0.17.0/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
+github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
+github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
 github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -702,6 +705,14 @@ github.com/moov-io/base v0.11.0 h1:1dhI8qsIxsUjMmbzE52ycyy2S1z3DGUN6swGYjSmOLs=
 github.com/moov-io/base v0.11.0/go.mod h1:jEkZukoSaJ4rDFoe00S5zuoLE+p3U3BEunSEPchgSbU=
 github.com/moov-io/base v0.11.1 h1:5qGfUr3eKWFmjttK2WllKgBg0Pnzx50+JBnRQQi8Gl0=
 github.com/moov-io/base v0.11.1/go.mod h1:kiWd5d0G3Ji+V9VhCNyzgfMNfbpzBblSL+QY2n2eywE=
+github.com/moov-io/base v0.11.2-0.20200928152256-789de616e101 h1:Ab3N7ayDoGdAwaFtphXw2aoobB41l0UZ1bJQTULVHpU=
+github.com/moov-io/base v0.11.2-0.20200928152256-789de616e101/go.mod h1:X3Rkm6lKCODm8zF7s43aawbyRDFyBdmEzO+NteVTj+A=
+github.com/moov-io/base v0.11.2-0.20201002162406-a4a21822c3ed h1:5romTcvSNfVUoTMpB0yiVOR5eJxjOEAjsGxZ8gGC27k=
+github.com/moov-io/base v0.11.2-0.20201002162406-a4a21822c3ed/go.mod h1:X3Rkm6lKCODm8zF7s43aawbyRDFyBdmEzO+NteVTj+A=
+github.com/moov-io/base v0.11.2-0.20201002180957-8150342846d2 h1:77QLONrQ7CQfCEATVnRH5BHPeZLwaC+98uYAJXCM61g=
+github.com/moov-io/base v0.11.2-0.20201002180957-8150342846d2/go.mod h1:X3Rkm6lKCODm8zF7s43aawbyRDFyBdmEzO+NteVTj+A=
+github.com/moov-io/base v0.11.2-0.20201003162845-340ece6ad5df h1:Mdyh9eI5SXGWPxYCo9VfHhqN+kPDElLtj2BemQL3HQ0=
+github.com/moov-io/base v0.11.2-0.20201003162845-340ece6ad5df/go.mod h1:X3Rkm6lKCODm8zF7s43aawbyRDFyBdmEzO+NteVTj+A=
 github.com/moov-io/customers v0.4.0-rc4/go.mod h1:wNz/qIiG24rJrjnK3VOvzj0MbdfGznj6INO/uyntgNM=
 github.com/moov-io/customers v0.4.0-rc4.0.20200519011716-05c4c319c49b/go.mod h1:wmBTMaZ7OzoXhDtLqGngNrEaRlsk7VFLxY0kl3HzoHc=
 github.com/moov-io/customers v0.4.0-rc5.0.20200605165738-057f20d4d580/go.mod h1:2viqzwFr1cp5gXL9lhOIXl7KE1pDIA8Z4I5smZBRUSo=
diff --git a/internal/database/database.go b/internal/database/database.go
index f9e1854..ee98d92 100644
--- a/internal/database/database.go
+++ b/internal/database/database.go
@@ -10,8 +10,8 @@ import (
 	"os"
 	"strings"
 
-	"github.com/go-kit/kit/log"
 	"github.com/lopezator/migrator"
+	"github.com/moov-io/base/log"
 )
 
 func New(logger log.Logger, _type string) (*sql.DB, error) {
diff --git a/internal/database/mysql.go b/internal/database/mysql.go
index 1651564..6f1e234 100644
--- a/internal/database/mysql.go
+++ b/internal/database/mysql.go
@@ -14,10 +14,10 @@ import (
 
 	"github.com/moov-io/base/docker"
 
-	"github.com/go-kit/kit/log"
 	kitprom "github.com/go-kit/kit/metrics/prometheus"
 	gomysql "github.com/go-sql-driver/mysql"
 	"github.com/lopezator/migrator"
+	"github.com/moov-io/base/log"
 	"github.com/ory/dockertest/v3"
 	stdprom "github.com/prometheus/client_golang/prometheus"
 )
@@ -182,7 +182,7 @@ func (my *mysql) Connect() (*sql.DB, error) {
 	}
 
 	migratorLogger := migrator.WithLogger(migrator.LoggerFunc(func(msg string, args ...interface{}) {
-		my.logger.Log("mysql", msg)
+		my.logger.WithKeyValue("package", "mysql").Log(msg)
 	}))
 
 	// Migrate our database
diff --git a/internal/database/sqlite.go b/internal/database/sqlite.go
index 1871215..325c17f 100644
--- a/internal/database/sqlite.go
+++ b/internal/database/sqlite.go
@@ -15,10 +15,10 @@ import (
 	"testing"
 	"time"
 
-	"github.com/go-kit/kit/log"
 	kitprom "github.com/go-kit/kit/metrics/prometheus"
 	"github.com/lopezator/migrator"
 	"github.com/mattn/go-sqlite3"
+	"github.com/moov-io/base/log"
 	stdprom "github.com/prometheus/client_golang/prometheus"
 )
 
@@ -174,7 +174,7 @@ func (s *sqlite) Connect() (*sql.DB, error) {
 
 	sqliteVersionLogOnce.Do(func() {
 		if v, _, _ := sqlite3.Version(); v != "" {
-			s.logger.Log("main", fmt.Sprintf("sqlite version %s", v))
+			s.logger.Log(fmt.Sprintf("sqlite version %s", v))
 		}
 	})
 
@@ -187,7 +187,7 @@ func (s *sqlite) Connect() (*sql.DB, error) {
 	}
 
 	migratorLogger := migrator.WithLogger(migrator.LoggerFunc(func(msg string, args ...interface{}) {
-		s.logger.Log("sqlite", msg)
+		s.logger.Log(fmt.Sprintf("sqlite: %s", msg))
 	}))
 
 	// Migrate our database
diff --git a/pkg/accounts/repository.go b/pkg/accounts/repository.go
index f5b5fcf..2204f87 100644
--- a/pkg/accounts/repository.go
+++ b/pkg/accounts/repository.go
@@ -15,7 +15,7 @@ import (
 
 	"github.com/moov-io/customers/pkg/client"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 type Repository interface {
diff --git a/pkg/accounts/router.go b/pkg/accounts/router.go
index ea64a20..9d070c8 100644
--- a/pkg/accounts/router.go
+++ b/pkg/accounts/router.go
@@ -22,11 +22,13 @@ import (
 	"github.com/moov-io/customers/pkg/secrets/mask"
 	"github.com/moov-io/customers/pkg/validator"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 func RegisterRoutes(logger log.Logger, r *mux.Router, accounts Repository, validations validator.Repository, fedClient fed.Client, keeper, transitKeeper *secrets.StringKeeper, validationStrategies map[validator.StrategyKey]validator.Strategy, ofac *AccountOfacSearcher) {
+	logger = logger.WithKeyValue("package", "accounts")
+
 	r.Methods("GET").Path("/customers/{customerID}/accounts").HandlerFunc(getCustomerAccounts(logger, accounts, fedClient))
 	r.Methods("POST").Path("/customers/{customerID}/accounts").HandlerFunc(createCustomerAccount(logger, accounts, fedClient, keeper, ofac))
 	r.Methods("POST").Path("/customers/{customerID}/accounts/{accountID}/decrypt").HandlerFunc(decryptAccountNumber(logger, accounts, keeper, transitKeeper))
@@ -130,18 +132,18 @@ func createCustomerAccount(logger log.Logger, repo Repository, fedClient fed.Cli
 			return
 		}
 		if err := request.validate(); err != nil {
-			logger.Log("accounts", fmt.Sprintf("problem validating account: %v", err), "requestID", moovhttp.GetRequestID(r))
+			logger.LogErrorF("problem validating account: %v", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 		if err := request.disfigure(keeper); err != nil {
-			logger.Log("accounts", fmt.Sprintf("problem disfiguring account: %v", err), "requestID", moovhttp.GetRequestID(r))
+			logger.LogErrorF("problem disfiguring account: %v", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		if _, err := fedClient.LookupInstitution(request.RoutingNumber); err != nil {
-			logger.Log("accounts", fmt.Sprintf("problem looking up routing number=%q: %v", request.RoutingNumber, err), "requestID", moovhttp.GetRequestID(r))
+			logger.LogErrorF("problem looking up routing number=%q: %v", request.RoutingNumber, err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -149,14 +151,14 @@ func createCustomerAccount(logger log.Logger, repo Repository, fedClient fed.Cli
 		customerID, userID := route.GetCustomerID(w, r), moovhttp.GetUserID(r)
 		account, err := repo.CreateCustomerAccount(customerID, userID, &request)
 		if err != nil {
-			logger.Log("accounts", fmt.Sprintf("problem saving account: %v", err), "requestID", moovhttp.GetRequestID(r))
+			logger.LogErrorF("problem saving account: %v", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		// Perform an OFAC search with the Customer information
 		if err := ofac.StoreAccountOFACSearch(account, requestID); err != nil {
-			logger.Log("accounts", fmt.Sprintf("error with OFAC search for account=%s: %v", account.AccountID, err), "requestID", requestID)
+			logger.LogErrorF("error with OFAC search for account=%s: %v", account.AccountID, err)
 		}
 
 		w.Header().Set("Content-Type", "application/json; charset=utf-8")
diff --git a/pkg/accounts/validate.go b/pkg/accounts/validate.go
index 177918d..b1c1bc1 100644
--- a/pkg/accounts/validate.go
+++ b/pkg/accounts/validate.go
@@ -17,7 +17,7 @@ import (
 	"github.com/moov-io/customers/pkg/secrets"
 	"github.com/moov-io/customers/pkg/validator"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func getAccountValidation(logger log.Logger, accounts Repository, validations validator.Repository) http.HandlerFunc {
diff --git a/pkg/configuration/router.go b/pkg/configuration/router.go
index 02a6476..6458b00 100644
--- a/pkg/configuration/router.go
+++ b/pkg/configuration/router.go
@@ -24,8 +24,8 @@ import (
 	"gocloud.dev/blob"
 	"gocloud.dev/gcerrors"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 const maxImageSize int64 = 20 * 1024 * 1024 // 20MB
@@ -53,6 +53,8 @@ func listAllowedContentTypes() string {
 }
 
 func RegisterRoutes(logger log.Logger, r *mux.Router, repo Repository, bucketFunc storage.BucketFunc) {
+	logger = logger.WithKeyValue("package", "configuration")
+
 	r.Methods("GET").Path("/configuration/customers").HandlerFunc(getOrganizationConfig(logger, repo))
 	r.Methods("PUT").Path("/configuration/customers").HandlerFunc(updateOrganizationConfig(logger, repo))
 	r.Methods("GET").Path("/configuration/logo").HandlerFunc(getOrganizationLogo(logger, repo, bucketFunc))
@@ -103,16 +105,17 @@ func updateOrganizationConfig(logger log.Logger, repo Repository) http.HandlerFu
 
 func getOrganizationLogo(logger log.Logger, repo Repository, bucketFactory storage.BucketFunc) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
-		requestID := moovhttp.GetRequestID(r)
 		organization := route.GetOrganization(w, r)
 		if organization == "" {
-			logger.Log("configuration", "get organization logo called with no organization header", "requestID", requestID)
+			logger.Log("get organization logo called with no organization header")
 			return
 		}
 
+		logger = logger.WithKeyValue("organization", organization)
+
 		bucket, err := bucketFactory()
 		if err != nil {
-			logger.Log("configuration", "problem retrieving logo image", "error", err, "organization", organization, "requestID", requestID)
+			logger.LogError("problem retrieving logo image", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -123,11 +126,12 @@ func getOrganizationLogo(logger log.Logger, repo Repository, bucketFactory stora
 			msg := "error retrieving logo file"
 			if gcerrors.Code(err) == gcerrors.NotFound {
 				msg = msg + " - file not found"
-				logger.Log("configuration", msg, "error", err, "organization", organization, "requestID", requestID)
+				logger.LogError(msg, err)
 				http.NotFound(w, r)
 				return
 			}
-			logger.Log("configuration", msg, "error", err, "organization", organization, "requestID", requestID)
+
+			logger.LogError(msg, err)
 			moovhttp.Problem(w, fmt.Errorf(msg))
 			return
 		}
@@ -135,7 +139,7 @@ func getOrganizationLogo(logger log.Logger, repo Repository, bucketFactory stora
 
 		fBytes, err := ioutil.ReadAll(rdr)
 		if err != nil || fBytes == nil {
-			logger.Log("configuration", "problem reading logo file", "error", err, "organization", organization, "requestID", requestID)
+			logger.LogError("problem reading logo file", err)
 			moovhttp.Problem(w, fmt.Errorf("problem reading logo file - error=%v", err))
 			return
 		}
@@ -148,16 +152,15 @@ func getOrganizationLogo(logger log.Logger, repo Repository, bucketFactory stora
 
 func uploadOrganizationLogo(logger log.Logger, repo Repository, bucketFactory storage.BucketFunc) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
-		requestID := moovhttp.GetRequestID(r)
 		organization := route.GetOrganization(w, r)
 		if organization == "" {
-			logger.Log("configuration", "upload logo called with no organization header", "requestID", requestID)
+			logger.Log("upload logo called with no organization header")
 			return
 		}
 
 		file, _, err := r.FormFile("file")
 		if file == nil || err != nil {
-			logger.Log("configuration", errMissingFile, "error", err, "organization", organization, "requestID", requestID)
+			logger.LogError(errMissingFile.Error(), err)
 			moovhttp.Problem(w, errMissingFile)
 			return
 		}
@@ -166,21 +169,22 @@ func uploadOrganizationLogo(logger log.Logger, repo Repository, bucketFactory st
 		// Detect the content type by reading the first 512 bytes of r.Body (read into file as we expect a multipart request)
 		buf := make([]byte, 512)
 		if _, err := file.Read(buf); err != nil && err != io.EOF {
-			logger.Log("configuration", "problem reading file", "error", err, "organization", organization, "requestID", requestID)
+			logger.LogError("problem reading file", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		contentType := http.DetectContentType(buf)
 		if !allowedContentTypes[contentType] {
-			logger.Log("configuration", "unsupported content type for logo image file", "error", err, "contentType", contentType, "organization", organization, "requestID", requestID)
+			logger.WithKeyValue("contentType", contentType).
+				Log("unsupported content type for logo image file")
 			moovhttp.Problem(w, errUnsupportedType)
 			return
 		}
 
 		bucket, err := bucketFactory()
 		if err != nil {
-			logger.Log("configuration", "problem uploading logo image", "error", err, "organization", organization, "requestID", requestID)
+			logger.LogError("problem uploading logo image", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -194,7 +198,7 @@ func uploadOrganizationLogo(logger log.Logger, repo Repository, bucketFactory st
 			ContentType:        contentType,
 		})
 		if err != nil {
-			logger.Log("configuration", "problem uploading logo image", "error", err, "organization", organization, "requestID", requestID)
+			logger.LogError("problem uploading logo image", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -202,7 +206,7 @@ func uploadOrganizationLogo(logger log.Logger, repo Repository, bucketFactory st
 
 		written, err := io.Copy(writer, io.LimitReader(io.MultiReader(bytes.NewReader(buf), file), maxImageSize))
 		if err != nil || written == 0 {
-			logger.Log("configuration", "problem uploading logo image", "error", err, "organization", organization, "requestID", requestID)
+			logger.LogError("problem uploading logo image", err)
 			moovhttp.Problem(w, fmt.Errorf("problem writing file - wrote %d bytes with error=%v", written, err))
 			return
 		}
diff --git a/pkg/customers/address.go b/pkg/customers/address.go
index b9f46ce..5451d9b 100644
--- a/pkg/customers/address.go
+++ b/pkg/customers/address.go
@@ -6,15 +6,17 @@ import (
 	"net/http"
 	"strings"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
 	moovhttp "github.com/moov-io/base/http"
+	"github.com/moov-io/base/log"
 
 	"github.com/moov-io/customers/pkg/client"
 	"github.com/moov-io/customers/pkg/route"
 )
 
 func AddCustomerAddressRoutes(logger log.Logger, r *mux.Router, repo CustomerRepository) {
+	logger = logger.WithKeyValue("package", "customers")
+
 	r.Methods("POST").Path("/customers/{customerID}/addresses").HandlerFunc(createCustomerAddress(logger, repo))
 	r.Methods("PUT").Path("/customers/{customerID}/addresses/{addressID}").HandlerFunc(updateCustomerAddress(logger, repo))
 	r.Methods("DELETE").Path("/customers/{customerID}/addresses/{addressID}").HandlerFunc(deleteCustomerAddress(logger, repo))
@@ -38,7 +40,7 @@ func createCustomerAddress(logger log.Logger, repo CustomerRepository) http.Hand
 			return
 		}
 
-		logger.Log("customers", fmt.Sprintf("added address for customer=%s", customerID), "requestID", requestID)
+		logger.Log(fmt.Sprintf("added address for customer=%s", customerID))
 
 		respondWithCustomer(logger, w, customerID, requestID, repo)
 	}
@@ -65,12 +67,13 @@ func updateCustomerAddress(logger log.Logger, repo CustomerRepository) http.Hand
 		}
 
 		if err := repo.updateCustomerAddress(customerID, addressId, req); err != nil {
-			logger.Log("customers", fmt.Sprintf("error updating customer's address: customer=%s address=%s: %v", customerID, addressId, err), "requestID", requestID)
+			logger.LogErrorF("error updating customer's address: customer=%s address=%s: %v", customerID, addressId, err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
-		logger.Log("customers", fmt.Sprintf("updating address=%s for customer=%s", addressId, customerID), "requestID", requestID)
+		logger.Log(fmt.Sprintf("updating address=%s for customer=%s", addressId, customerID))
+
 		respondWithCustomer(logger, w, customerID, requestID, repo)
 	}
 }
@@ -83,16 +86,16 @@ func deleteCustomerAddress(logger log.Logger, repo CustomerRepository) http.Hand
 		if customerID == "" || addressId == "" {
 			return
 		}
-		requestID := moovhttp.GetRequestID(r)
 
 		err := repo.deleteCustomerAddress(customerID, addressId)
 		if err != nil {
+			logger.LogErrorF("error deleting customer's address: customer=%s address=%s: %v", customerID, addressId, err)
 			moovhttp.Problem(w, err)
-			logger.Log("customers", fmt.Sprintf("error deleting customer's address: customer=%s address=%s: %v", customerID, addressId, err), "requestID", requestID)
 			return
 		}
 
-		logger.Log("customers", fmt.Sprintf("successfully deleted address=%s for customer=%s", addressId, customerID), "requestID", requestID)
+		logger.Log(fmt.Sprintf("successfully deleted address=%s for customer=%s", addressId, customerID))
+
 		w.WriteHeader(http.StatusNoContent)
 	}
 }
diff --git a/pkg/customers/approval.go b/pkg/customers/approval.go
index dc8a0f3..e9b4543 100644
--- a/pkg/customers/approval.go
+++ b/pkg/customers/approval.go
@@ -14,7 +14,7 @@ import (
 	"github.com/moov-io/customers/pkg/client"
 	"github.com/moov-io/customers/pkg/route"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func updateCustomerStatus(logger log.Logger, repo CustomerRepository) http.HandlerFunc {
diff --git a/pkg/customers/approval_ofac.go b/pkg/customers/approval_ofac.go
index 8180ca1..b3844ca 100644
--- a/pkg/customers/approval_ofac.go
+++ b/pkg/customers/approval_ofac.go
@@ -21,8 +21,8 @@ import (
 	"github.com/moov-io/customers/pkg/route"
 	"github.com/moov-io/customers/pkg/watchman"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 var (
@@ -98,6 +98,8 @@ func (s *OFACSearcher) storeCustomerOFACSearch(cust *client.Customer, requestID
 }
 
 func AddOFACRoutes(logger log.Logger, r *mux.Router, repo CustomerRepository, ofac *OFACSearcher) {
+	logger = logger.WithKeyValue("package", "customers")
+
 	r.Methods("GET").Path("/customers/{customerID}/ofac").HandlerFunc(getLatestCustomerOFACSearch(logger, repo))
 	r.Methods("PUT").Path("/customers/{customerID}/refresh/ofac").HandlerFunc(refreshOFACSearch(logger, repo, ofac))
 }
@@ -128,7 +130,7 @@ func refreshOFACSearch(logger log.Logger, repo CustomerRepository, ofac *OFACSea
 		w = route.Responder(logger, w, r)
 		w.Header().Set("Content-Type", "application/json; charset=utf-8")
 
-		requestID, userID := moovhttp.GetRequestID(r), moovhttp.GetUserID(r)
+		requestID := moovhttp.GetRequestID(r)
 		customerID := route.GetCustomerID(w, r)
 		if customerID == "" {
 			return
@@ -140,27 +142,26 @@ func refreshOFACSearch(logger log.Logger, repo CustomerRepository, ofac *OFACSea
 			return
 		}
 
-		logger.Log("ofac", fmt.Sprintf("running live OFAC search for customer=%s", customerID), "requestID", requestID, "userID", userID)
+		logger.Log(fmt.Sprintf("running live OFAC search for customer=%s", customerID))
 
 		if err := ofac.storeCustomerOFACSearch(cust, requestID); err != nil {
-			logger.Log("ofac", fmt.Sprintf("error refreshing ofac search: %v", err))
+			logger.LogErrorF("error refreshing ofac search: %v", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		result, err := repo.getLatestCustomerOFACSearch(customerID)
 		if err != nil {
-			logger.Log("ofac", fmt.Sprintf("error getting latest ofac search: %v", err))
+			logger.LogErrorF("error getting latest ofac search: %v", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		if result.Blocked {
-			err = fmt.Errorf("customer=%s matched against OFAC entity=%s with a score of %.2f - rejecting customer", cust.CustomerID, result.EntityID, result.Match)
-			logger.Log("ofac", err.Error(), "requestID", requestID, "userID", userID)
+			logger.LogErrorF("customer=%s matched against OFAC entity=%s with a score of %.2f - rejecting customer", cust.CustomerID, result.EntityID, result.Match)
 
 			if err := repo.updateCustomerStatus(cust.CustomerID, client.REJECTED, "manual OFAC refresh"); err != nil {
-				logger.Log("ofac", fmt.Sprintf("error updating customer=%s error=%v", cust.CustomerID, err))
+				logger.LogErrorF("error updating customer=%s error=%v", cust.CustomerID, err)
 				moovhttp.Problem(w, err)
 				return
 			}
diff --git a/pkg/customers/customer_search.go b/pkg/customers/customer_search.go
index 44fc3b9..68d2267 100644
--- a/pkg/customers/customer_search.go
+++ b/pkg/customers/customer_search.go
@@ -10,9 +10,9 @@ import (
 	"net/http"
 	"strings"
 
-	"github.com/go-kit/kit/log"
 	moovhttp "github.com/moov-io/base/http"
 
+	"github.com/moov-io/base/log"
 	"github.com/moov-io/customers/pkg/client"
 	"github.com/moov-io/customers/pkg/route"
 )
@@ -39,7 +39,7 @@ func searchCustomers(logger log.Logger, repo CustomerRepository) http.HandlerFun
 			return
 		}
 
-		logger.Log("customers", fmt.Sprintf("found %d customers in search", len(customers)))
+		logger.Log(fmt.Sprintf("found %d customers in search", len(customers)))
 
 		w.Header().Set("Content-Type", "application/json; charset=utf-8")
 		w.WriteHeader(http.StatusOK)
diff --git a/pkg/customers/customer_ssn.go b/pkg/customers/customer_ssn.go
index 4e193ef..442eb5b 100644
--- a/pkg/customers/customer_ssn.go
+++ b/pkg/customers/customer_ssn.go
@@ -13,7 +13,7 @@ import (
 
 	"github.com/moov-io/customers/pkg/secrets"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 type SSN struct {
diff --git a/pkg/customers/customers.go b/pkg/customers/customers.go
index 18d4587..69761e9 100644
--- a/pkg/customers/customers.go
+++ b/pkg/customers/customers.go
@@ -22,11 +22,13 @@ import (
 	"github.com/moov-io/customers/pkg/model"
 	"github.com/moov-io/customers/pkg/route"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 func AddCustomerRoutes(logger log.Logger, r *mux.Router, repo CustomerRepository, customerSSNStorage *ssnStorage, ofac *OFACSearcher) {
+	logger = logger.WithKeyValue("package", "customers")
+
 	r.Methods("GET").Path("/customers").HandlerFunc(searchCustomers(logger, repo))
 	r.Methods("GET").Path("/customers/{customerID}").HandlerFunc(getCustomer(logger, repo))
 	r.Methods("PUT").Path("/customers/{customerID}").HandlerFunc(updateCustomer(logger, repo, customerSSNStorage))
@@ -88,7 +90,7 @@ func deleteCustomer(logger log.Logger, repo CustomerRepository) func(http.Respon
 func respondWithCustomer(logger log.Logger, w http.ResponseWriter, customerID string, requestID string, repo CustomerRepository) {
 	cust, err := repo.GetCustomer(customerID)
 	if err != nil {
-		logger.Log("customers", fmt.Sprintf("GetCustomer: lookup: %v", err), "requestID", requestID)
+		logger.LogErrorF("getCustomer: lookup: %v", err)
 		moovhttp.Problem(w, err)
 		return
 	}
@@ -249,42 +251,42 @@ func createCustomer(logger log.Logger, repo CustomerRepository, customerSSNStora
 			return
 		}
 		if err := req.validate(); err != nil {
-			logger.Log("customers", "error validating new customer", "error", err, "requestID", requestID)
+			logger.LogError("error validating new customer", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		cust, ssn, err := req.asCustomer(customerSSNStorage)
 		if err != nil {
-			logger.Log("customers", fmt.Sprintf("problem transforming request into Customer=%s: %v", cust.CustomerID, err), "requestID", requestID)
+			logger.LogErrorF("problem transforming request into Customer=%s: %v", cust.CustomerID, err)
 			moovhttp.Problem(w, err)
 			return
 		}
 		if ssn != nil {
 			err := customerSSNStorage.repo.saveCustomerSSN(ssn)
 			if err != nil {
-				logger.Log("customers", fmt.Sprintf("problem saving SSN for Customer=%s: %v", cust.CustomerID, err), "requestID", requestID)
+				logger.LogErrorF("problem saving SSN for Customer=%s: %v", cust.CustomerID, err)
 				moovhttp.Problem(w, fmt.Errorf("saveCustomerSSN: %v", err))
 				return
 			}
 		}
 		if err := repo.CreateCustomer(cust, organization); err != nil {
-			logger.Log("customers", fmt.Sprintf("CreateCustomer: %v", err), "requestID", requestID)
+			logger.LogErrorF("createCustomer: %v", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 		if err := repo.replaceCustomerMetadata(cust.CustomerID, cust.Metadata); err != nil {
-			logger.Log("customers", fmt.Sprintf("updating metadata for customer=%s failed: %v", cust.CustomerID, err), "requestID", requestID)
+			logger.LogErrorF("updating metadata for customer=%s failed: %v", cust.CustomerID, err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		// Perform an OFAC search with the Customer information
 		if err := ofac.storeCustomerOFACSearch(cust, requestID); err != nil {
-			logger.Log("customers", fmt.Sprintf("error with OFAC search for customer=%s: %v", cust.CustomerID, err), "requestID", requestID)
+			logger.LogErrorF("error with OFAC search for customer=%s: %v", cust.CustomerID, err)
 		}
 
-		logger.Log("customers", fmt.Sprintf("created customer=%s", cust.CustomerID), "requestID", requestID)
+		logger.Log(fmt.Sprintf("created customer=%s", cust.CustomerID))
 
 		cust, err = repo.GetCustomer(cust.CustomerID)
 		if err != nil {
@@ -302,7 +304,7 @@ func updateCustomer(logger log.Logger, repo CustomerRepository, customerSSNStora
 		w = route.Responder(logger, w, r)
 		w.Header().Set("Content-Type", "application/json; charset=utf-8")
 
-		requestID, organization := moovhttp.GetRequestID(r), route.GetOrganization(w, r)
+		organization := route.GetOrganization(w, r)
 		if organization == "" {
 			return
 		}
@@ -318,38 +320,38 @@ func updateCustomer(logger log.Logger, repo CustomerRepository, customerSSNStora
 			return
 		}
 		if err := req.validate(); err != nil {
-			logger.Log("customers", "error validating customer payload", "error", err, "requestID", requestID)
+			logger.LogError("error validating customer payload", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		cust, ssn, err := req.asCustomer(customerSSNStorage)
 		if err != nil {
-			logger.Log("customers", fmt.Sprintf("transforming request into Customer=%s: %v", cust.CustomerID, err), "requestID", requestID)
+			logger.LogErrorF("transforming request into Customer=%s: %v", cust.CustomerID, err)
 			moovhttp.Problem(w, err)
 			return
 		}
 		if ssn != nil {
 			err := customerSSNStorage.repo.saveCustomerSSN(ssn)
 			if err != nil {
-				logger.Log("customers", fmt.Sprintf("error saving SSN for Customer=%s: %v", cust.CustomerID, err), "requestID", requestID)
+				logger.LogErrorF("error saving SSN for Customer=%s: %v", cust.CustomerID, err)
 				moovhttp.Problem(w, fmt.Errorf("saving customer's SSN: %v", err))
 				return
 			}
 		}
 		if err := repo.updateCustomer(cust, organization); err != nil {
-			logger.Log("customers", fmt.Sprintf("error updating customer: %v", err), "requestID", requestID)
+			logger.LogErrorF("error updating customer: %v", err)
 			moovhttp.Problem(w, fmt.Errorf("updating customer: %v", err))
 			return
 		}
 
 		if err := repo.replaceCustomerMetadata(cust.CustomerID, cust.Metadata); err != nil {
-			logger.Log("customers", fmt.Sprintf("error updating metadata for customer=%s: %v", cust.CustomerID, err), "requestID", requestID)
+			logger.LogErrorF("error updating metadata for customer=%s: %v", cust.CustomerID, err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
-		logger.Log("customers", fmt.Sprintf("updated customer=%s", cust.CustomerID), "requestID", requestID)
+		logger.Log(fmt.Sprintf("updated customer=%s", cust.CustomerID))
 		cust, err = repo.GetCustomer(cust.CustomerID)
 		if err != nil {
 			moovhttp.Problem(w, err)
diff --git a/pkg/documents/disclaimers.go b/pkg/documents/disclaimers.go
index de85b90..d3ce826 100644
--- a/pkg/documents/disclaimers.go
+++ b/pkg/documents/disclaimers.go
@@ -19,8 +19,8 @@ import (
 	"github.com/moov-io/customers/pkg/client"
 	"github.com/moov-io/customers/pkg/route"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 var (
diff --git a/pkg/documents/documents.go b/pkg/documents/documents.go
index 63c7300..3ebcb57 100644
--- a/pkg/documents/documents.go
+++ b/pkg/documents/documents.go
@@ -24,8 +24,8 @@ import (
 	"github.com/moov-io/customers/pkg/documents/storage"
 	"github.com/moov-io/customers/pkg/route"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 	"gocloud.dev/blob"
 	"gocloud.dev/secrets"
 )
@@ -46,6 +46,8 @@ const (
 )
 
 func AddDocumentRoutes(logger log.Logger, r *mux.Router, repo DocumentRepository, keeper *secrets.Keeper, bucketFactory storage.BucketFunc) {
+	logger = logger.WithKeyValue("package", "documents")
+
 	r.Methods("GET").Path("/customers/{customerID}/documents").HandlerFunc(getCustomerDocuments(logger, repo))
 	r.Methods("POST").Path("/customers/{customerID}/documents").HandlerFunc(uploadCustomerDocument(logger, repo, keeper, bucketFactory))
 	r.Methods("GET").Path("/customers/{customerID}/documents/{documentID}").HandlerFunc(retrieveRawDocument(logger, repo, keeper, bucketFactory))
@@ -72,7 +74,7 @@ func getCustomerDocuments(logger log.Logger, repo DocumentRepository) http.Handl
 
 		docs, err := repo.getCustomerDocuments(customerID, organization)
 		if err != nil {
-			logger.Log("documents", fmt.Sprintf("failed to %v", err), "customerID", customerID)
+			logger.WithKeyValue("customerID", customerID).LogError("failed to get customer document", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -99,11 +101,13 @@ func uploadCustomerDocument(logger log.Logger, repo DocumentRepository, keeper *
 	return func(w http.ResponseWriter, r *http.Request) {
 		w = route.Responder(logger, w, r)
 
-		requestID := moovhttp.GetRequestID(r)
 		customerID := route.GetCustomerID(w, r)
 		if customerID == "" {
 			return
 		}
+
+		logger = logger.WithKeyValue("customerID", customerID)
+
 		documentType, err := readDocumentType(r.URL.Query().Get("type"))
 		if err != nil {
 			moovhttp.Problem(w, err)
@@ -115,18 +119,18 @@ func uploadCustomerDocument(logger log.Logger, repo DocumentRepository, keeper *
 		file, fileHeader, err := r.FormFile("file")
 		if err != nil {
 			if strings.Contains(err.Error(), "request body too large") {
-				logger.Log("documents", "max form size exceeded", "customerID", customerID, "requestID", requestID)
+				logger.LogError("max form size exceeded", err)
 				moovhttp.Problem(w, fmt.Errorf("request body exceeds maximum size of %s", maxFormSize))
 				return
 			}
-			logger.Log("documents", "error reading form file", "error", err, "customerID", customerID, "requestID", requestID)
+			logger.LogError("error reading form file", err)
 			moovhttp.Problem(w, fmt.Errorf("expected multipart upload with key of 'file' error=%v", err))
 			return
 		}
 		defer file.Close()
 
 		if fileHeader.Size > int64(maxDocumentSize) {
-			logger.Log("documents", "max file size exceeded", "customerID", customerID, "requestID", requestID)
+			logger.LogErrorF("failed to peek: %v", err)
 			moovhttp.Problem(w, fmt.Errorf("file exceeds maximum size of %s", maxDocumentSize))
 			return
 		}
@@ -134,7 +138,7 @@ func uploadCustomerDocument(logger log.Logger, repo DocumentRepository, keeper *
 		fileReader := bufio.NewReader(file)
 		sniff, err := fileReader.Peek(512)
 		if err != nil && err != io.EOF {
-			logger.Log("documents", "peek failed", "error", err, "customerID", customerID, "requestID", requestID)
+			logger.LogError("peek failed", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -143,7 +147,7 @@ func uploadCustomerDocument(logger log.Logger, repo DocumentRepository, keeper *
 		// Grab our cloud bucket before writing into our database
 		bucket, err := bucketFactory()
 		if err != nil {
-			logger.Log("documents", fmt.Sprintf("failed to create bucket: %v", err), "customerID", customerID, "requestID", requestID)
+			logger.LogError("failed to create bucket", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -156,11 +160,11 @@ func uploadCustomerDocument(logger log.Logger, repo DocumentRepository, keeper *
 			UploadedAt:  time.Now(),
 		}
 		if err := repo.writeCustomerDocument(customerID, doc); err != nil {
-			logger.Log("documents", fmt.Sprintf("failed to %v", err), "customerID", customerID, "requestID", requestID)
+			logger.LogError("failed to write customer document", err)
 			moovhttp.Problem(w, err)
 			return
 		}
-		logger.Log("documents", fmt.Sprintf("uploading document=%s (content-type: %s) for customer=%s", doc.DocumentID, contentType, customerID), "requestID", requestID)
+		logger.Log(fmt.Sprintf("uploading document=%s (content-type: %s)", doc.DocumentID, contentType))
 
 		// Write our document from the request body
 		ctx, cancelFn := context.WithTimeout(context.TODO(), 60*time.Second)
@@ -169,26 +173,26 @@ func uploadCustomerDocument(logger log.Logger, repo DocumentRepository, keeper *
 		fBytes := make([]byte, fileHeader.Size)
 		_, err = fileReader.Read(fBytes)
 		if err != nil {
-			logger.Log("documents", "read failed", "error", err, "customerID", customerID, "requestID", requestID)
+			logger.LogError("read failed", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 		encryptedDoc, err := keeper.Encrypt(ctx, fBytes)
 		if err != nil {
-			logger.Log("documents", "failed to encrypt document", "error", err, "customer", customerID, "requestID", requestID)
+			logger.LogError("failed to encrypt document", err)
 			moovhttp.Problem(w, fmt.Errorf("file upload error - %v", err))
 			return
 		}
 
 		documentKey := makeDocumentKey(customerID, doc.DocumentID)
-		logger.Log("documents", fmt.Sprintf("writing %s", documentKey), "requestID", requestID)
+		logger.Log(fmt.Sprintf("writing %s", documentKey))
 
 		err = bucket.WriteAll(ctx, documentKey, encryptedDoc, &blob.WriterOptions{
 			ContentDisposition: "inline",
 			ContentType:        contentType,
 		})
 		if err != nil {
-			logger.Log("documents", fmt.Sprintf("problem uploading document=%s: %v", doc.DocumentID, err), "requestID", requestID)
+			logger.LogError("problem uploading document", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -203,7 +207,6 @@ func retrieveRawDocument(logger log.Logger, repo DocumentRepository, keeper *sec
 	return func(w http.ResponseWriter, r *http.Request) {
 		w = route.Responder(logger, w, r)
 
-		requestID := moovhttp.GetRequestID(r)
 		customerID, documentID := route.GetCustomerID(w, r), getDocumentID(w, r)
 		if customerID == "" || documentID == "" {
 			return
@@ -213,10 +216,13 @@ func retrieveRawDocument(logger log.Logger, repo DocumentRepository, keeper *sec
 			return
 		}
 
+		logger = logger.WithKeyValue("customerID", customerID).
+			WithKeyValue("documentID", documentID)
+
 		// reject the request if the document is deleted
 		if exists, err := repo.exists(customerID, documentID, organization); !exists || err != nil {
 			if err != nil {
-				logger.Log("documents", fmt.Sprintf("failed to %v", err), "customerID", customerID, "documentID", documentID, "requestID", requestID)
+				logger.LogError("failed to check document existence", err)
 			}
 			http.NotFound(w, r)
 			return
@@ -242,14 +248,14 @@ func retrieveRawDocument(logger log.Logger, repo DocumentRepository, keeper *sec
 
 		encryptedDoc, err := ioutil.ReadAll(rdr)
 		if err != nil {
-			logger.Log("documents", "failed reading document from storage bucket", "error", err, "customerID", customerID, "documentID", documentID, "requestID", requestID)
+			logger.LogError("failed reading document from storage bucket", err)
 			moovhttp.Problem(w, err)
 			return
 		}
 
 		doc, err := keeper.Decrypt(ctx, encryptedDoc)
 		if err != nil {
-			logger.Log("documents", "failed to decrypt document", "error", err, "customerID", customerID, "documentID", documentID, "requestID", requestID)
+			logger.LogError("failed to decrypt document", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -266,21 +272,23 @@ func retrieveRawDocument(logger log.Logger, repo DocumentRepository, keeper *sec
 func deleteCustomerDocument(logger log.Logger, repo DocumentRepository) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		w = route.Responder(logger, w, r)
-		requestID := moovhttp.GetRequestID(r)
 
 		customerID, documentID := route.GetCustomerID(w, r), getDocumentID(w, r)
 		if customerID == "" || documentID == "" {
 			return
 		}
 
+		logger = logger.WithKeyValue("customerID", customerID).
+			WithKeyValue("documentID", documentID)
+
 		err := repo.deleteCustomerDocument(customerID, documentID)
 		if err != nil {
+			logger.LogError("failed to delete document", err)
 			moovhttp.Problem(w, fmt.Errorf("failed to %v", err))
-			logger.Log("documents", fmt.Sprintf("deleting document=%s for customer=%s: %v", documentID, customerID, err), "requestID", requestID)
 			return
 		}
 
-		logger.Log("documents", fmt.Sprintf("successfully deleted document=%s for customer=%s", documentID, customerID), "requestID", requestID)
+		logger.Log("successfully deleted document")
 
 		w.WriteHeader(http.StatusNoContent)
 	}
diff --git a/pkg/documents/repository.go b/pkg/documents/repository.go
index 5dffd7a..0d99d7a 100644
--- a/pkg/documents/repository.go
+++ b/pkg/documents/repository.go
@@ -9,7 +9,7 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 	"github.com/moov-io/customers/pkg/client"
 )
 
diff --git a/pkg/documents/storage/bucket.go b/pkg/documents/storage/bucket.go
index 23ad062..508cee1 100644
--- a/pkg/documents/storage/bucket.go
+++ b/pkg/documents/storage/bucket.go
@@ -16,7 +16,7 @@ import (
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/session"
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 	"gocloud.dev/blob"
 	"gocloud.dev/blob/fileblob"
 	"gocloud.dev/blob/gcsblob"
@@ -27,6 +27,8 @@ import (
 type BucketFunc func() (*blob.Bucket, error)
 
 func GetBucket(logger log.Logger, bucketName, cloudProvider string, FileblobSigner *fileblob.URLSignerHMAC) BucketFunc {
+	logger = logger.WithKeyValue("package", "storage")
+
 	return func() (*blob.Bucket, error) {
 		ctx, cancelFn := context.WithTimeout(context.TODO(), 10*time.Second)
 		defer cancelFn()
@@ -66,10 +68,10 @@ func awsBucket(ctx context.Context, logger log.Logger, bucketName string) (*blob
 
 	bucket, err := s3blob.OpenBucket(ctx, s, bucketName, nil)
 	if err != nil {
-		logger.Log("storage", fmt.Sprintf("ERROR creating %s aws bucket: %v", bucketName, err))
+		logger.LogErrorF("ERROR creating %s aws bucket: %v", bucketName, err)
 		return nil, err
 	}
-	logger.Log("storage", fmt.Sprintf("created %s aws bucket: %T", bucketName, bucket))
+	logger.Log(fmt.Sprintf("created %s aws bucket: %T", bucketName, bucket))
 	return bucket, nil
 }
 
@@ -85,7 +87,7 @@ func fileBucket(ctx context.Context, logger log.Logger, bucketName string, signe
 	if err := os.Mkdir(bucketName, 0777); strings.Contains(bucketName, "..") || (err != nil && !os.IsExist(err)) {
 		return nil, fmt.Errorf("problem creating %s error=%v", bucketName, err)
 	}
-	logger.Log("storage", fmt.Sprintf("created %s for file bucket", bucketName))
+	logger.LogErrorF("created %s for file bucket", bucketName)
 	return fileblob.OpenBucket(bucketName, &fileblob.Options{
 		URLSigner: signer,
 	})
@@ -105,9 +107,9 @@ func gcpBucket(ctx context.Context, logger log.Logger, bucketName string) (*blob
 
 	bucket, err := gcsblob.OpenBucket(ctx, c, bucketName, nil)
 	if err != nil {
-		logger.Log("storage", fmt.Sprintf("ERROR creating %s gcp bucket: %v", bucketName, err))
+		logger.LogErrorF("ERROR creating %s gcp bucket: %v", bucketName, err)
 		return nil, err
 	}
-	logger.Log("storage", fmt.Sprintf("created %s gcp bucket: %v", bucketName, err))
+	logger.Log(fmt.Sprintf("created %s gcp bucket: %v", bucketName, err))
 	return bucket, nil
 }
diff --git a/pkg/documents/storage/files.go b/pkg/documents/storage/files.go
index 40a5042..b322984 100644
--- a/pkg/documents/storage/files.go
+++ b/pkg/documents/storage/files.go
@@ -16,12 +16,14 @@ import (
 	moovhttp "github.com/moov-io/base/http"
 	"github.com/moov-io/customers/pkg/route"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 	"gocloud.dev/blob/fileblob"
 )
 
 func AddFileblobRoutes(logger log.Logger, r *mux.Router, signer *fileblob.URLSignerHMAC, bucketFactory BucketFunc) {
+	logger = logger.WithKeyValue("package", "storage")
+
 	if v := os.Getenv("FILEBLOB_BASE_URL"); v != "" {
 		u, err := url.Parse(v)
 		if u != nil && err == nil {
@@ -60,7 +62,7 @@ func proxyLocalFile(logger log.Logger, signer *fileblob.URLSignerHMAC, bucketFac
 		}
 		defer rdr.Close()
 
-		logger.Log("files", fmt.Sprintf("proxying document=%s contentType=%s", key, rdr.ContentType()), "requestID", moovhttp.GetRequestID(r))
+		logger.Log(fmt.Sprintf("proxying document=%s contentType=%s", key, rdr.ContentType()))
 
 		w.Header().Set("Content-Disposition", "inline")
 		w.Header().Set("Content-Length", fmt.Sprintf("%d", rdr.Size()))
diff --git a/pkg/fed/client.go b/pkg/fed/client.go
index f778487..51a7ae3 100644
--- a/pkg/fed/client.go
+++ b/pkg/fed/client.go
@@ -17,7 +17,7 @@ import (
 	moovfed "github.com/moov-io/fed/client"
 
 	"github.com/antihax/optional"
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 type Client interface {
@@ -105,7 +105,8 @@ func NewClient(logger log.Logger, endpoint string, debug bool) Client {
 		}
 	}
 
-	logger.Log("fed", fmt.Sprintf("using %s for FED address", conf.BasePath))
+	logger = logger.WithKeyValue("package", "fed")
+	logger.Log(fmt.Sprintf("using %s for FED address", conf.BasePath))
 
 	return &moovClient{
 		underlying: moovfed.NewAPIClient(conf),
diff --git a/pkg/fed/fed.go b/pkg/fed/fed.go
index c8cb128..910a445 100644
--- a/pkg/fed/fed.go
+++ b/pkg/fed/fed.go
@@ -10,7 +10,7 @@ import (
 
 	"github.com/moov-io/customers/internal/util"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func Cache(logger log.Logger, endpoint string, debug bool) Client {
diff --git a/pkg/paygate/client.go b/pkg/paygate/client.go
index 638fc30..812fa36 100644
--- a/pkg/paygate/client.go
+++ b/pkg/paygate/client.go
@@ -16,7 +16,7 @@ import (
 	"github.com/moov-io/base/k8s"
 	"github.com/moov-io/paygate/pkg/client"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 type Client interface {
@@ -98,7 +98,7 @@ func (c *moovClient) InitiateMicroDeposits(userID string, destination client.Des
 		return fmt.Errorf("unexpected HTTP status: %s", resp.Status)
 	}
 
-	c.logger.Log("paygate", fmt.Sprintf("created microDepositID=%s for accountID=%s", micro.MicroDepositID, destination.AccountID))
+	c.logger.Log(fmt.Sprintf("created microDepositID=%s for accountID=%s", micro.MicroDepositID, destination.AccountID))
 
 	return nil
 }
@@ -124,7 +124,8 @@ func NewClient(logger log.Logger, endpoint string, debug bool) Client {
 		}
 	}
 
-	logger.Log("paygate", fmt.Sprintf("using %s for PayGate address", conf.BasePath))
+	logger = logger.WithKeyValue("package", "paygate")
+	logger.Log(fmt.Sprintf("using %s for PayGate address", conf.BasePath))
 
 	return &moovClient{
 		logger:     logger,
diff --git a/pkg/reports/router.go b/pkg/reports/router.go
index 3edf9d5..b5ee268 100644
--- a/pkg/reports/router.go
+++ b/pkg/reports/router.go
@@ -6,9 +6,9 @@ import (
 	"net/http"
 	"strings"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
 	moovhttp "github.com/moov-io/base/http"
+	"github.com/moov-io/base/log"
 
 	"github.com/moov-io/customers/pkg/accounts"
 	"github.com/moov-io/customers/pkg/client"
@@ -22,6 +22,8 @@ func AddRoutes(
 	customerRepo customers.CustomerRepository,
 	accountRepo accounts.Repository,
 ) {
+	logger = logger.WithKeyValue("package", "reports")
+
 	r.Methods("GET").Path("/reports/accounts").HandlerFunc(getCustomerAccounts(logger, customerRepo, accountRepo))
 }
 
@@ -37,7 +39,6 @@ func getCustomerAccounts(
 ) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		w = route.Responder(logger, w, r)
-		requestID := moovhttp.GetRequestID(r)
 
 		accountIDsInput := r.URL.Query().Get("accountIDs")
 		accountIDsInput = strings.TrimSpace(accountIDsInput)
@@ -51,7 +52,7 @@ func getCustomerAccounts(
 
 		allAccounts, err := accountRepo.GetCustomerAccountsByIDs(accountIDs)
 		if err != nil {
-			logger.Log("customers", "error getting customers' accounts", "error", err, "requestID", requestID)
+			logger.LogError("error getting customers' accounts", err)
 			moovhttp.Problem(w, err)
 			return
 		}
@@ -60,7 +61,7 @@ func getCustomerAccounts(
 		for _, acc := range allAccounts {
 			cust, err := customerRepo.GetCustomer(acc.CustomerID)
 			if err != nil {
-				logger.Log("customers", "error getting customer", "error", err, "requestID", requestID)
+				logger.LogError("error getting customer", err)
 				moovhttp.Problem(w, err)
 				return
 			}
diff --git a/pkg/route/http.go b/pkg/route/http.go
index 875bcf6..e1d0642 100644
--- a/pkg/route/http.go
+++ b/pkg/route/http.go
@@ -11,11 +11,10 @@ import (
 	"strconv"
 	"strings"
 
-	moovhttp "github.com/moov-io/base/http"
 	// "github.com/moov-io/base/idempotent/lru" // TODO(adam): use with LRU below
 
-	"github.com/go-kit/kit/log"
 	"github.com/go-kit/kit/metrics/prometheus"
+	"github.com/moov-io/base/log"
 	stdprometheus "github.com/prometheus/client_golang/prometheus"
 )
 
@@ -30,7 +29,8 @@ var (
 
 func Responder(logger log.Logger, w http.ResponseWriter, r *http.Request) http.ResponseWriter {
 	route := fmt.Sprintf("%s-%s", strings.ToLower(r.Method), cleanMetricsPath(r.URL.Path))
-	return moovhttp.Wrap(logger, routeHistogram.With("route", route), w, r)
+
+	return Wrap(logger, routeHistogram.With("route", route), w, r)
 }
 
 var baseIdRegex = regexp.MustCompile(`([a-f0-9]{40})`)
diff --git a/pkg/route/response.go b/pkg/route/response.go
new file mode 100644
index 0000000..fae61a8
--- /dev/null
+++ b/pkg/route/response.go
@@ -0,0 +1,95 @@
+package route
+
+import (
+	"net/http"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/go-kit/kit/metrics"
+	"github.com/moov-io/base/log"
+)
+
+// To avoid changes into base/http.Wrap and its dependencies (Fed, Watchman,
+// ...) base/http.Wrap code is duplicated here. When we rewrite Customers
+// routing based on templater we will get rid of this code. Agree? Thoughts?
+
+// ResponseWriter implements Go's standard library http.ResponseWriter to complete HTTP requests
+type ResponseWriter struct {
+	http.ResponseWriter
+
+	start   time.Time
+	request *http.Request
+	metric  metrics.Histogram
+
+	headersWritten bool // set on WriteHeader
+
+	log log.Logger
+}
+
+// WriteHeader sends an HTTP response header with the provided status code, records response duration,
+// and optionally records the HTTP metadata in a go-kit log.Logger
+func (w *ResponseWriter) WriteHeader(code int) {
+	if w == nil || w.headersWritten {
+		return
+	}
+	w.headersWritten = true
+
+	// Headers
+	SetAccessControlAllowHeaders(w, w.request.Header.Get("Origin"))
+	defer w.ResponseWriter.WriteHeader(code)
+
+	// Record route timing
+	diff := time.Since(w.start)
+	if w.metric != nil {
+		w.metric.Observe(diff.Seconds())
+	}
+
+	// Skip Go's content sniff here to speed up response timing for client
+	if w.ResponseWriter.Header().Get("Content-Type") == "" {
+		w.ResponseWriter.Header().Set("Content-Type", "text/plain")
+		w.ResponseWriter.Header().Set("X-Content-Type-Options", "nosniff")
+	}
+
+	if requestID := GetRequestID(w.request); requestID != "" && w.log != nil {
+		w.log.WithMap(map[string]string{
+			"method":    w.request.Method,
+			"path":      w.request.URL.Path,
+			"status":    strconv.Itoa(code),
+			"duration":  diff.String(),
+			"requestID": requestID,
+		})
+	}
+}
+
+// Wrap returns a ResponseWriter usable by applications. No parts of the Request are inspected or ResponseWriter modified.
+func Wrap(logger log.Logger, m metrics.Histogram, w http.ResponseWriter, r *http.Request) *ResponseWriter {
+	now := time.Now()
+	return &ResponseWriter{
+		ResponseWriter: w,
+		start:          now,
+		request:        r,
+		metric:         m,
+		log:            logger,
+	}
+}
+
+// SetAccessControlAllowHeaders writes Access-Control-Allow-* headers to a response to allow
+// for further CORS-allowed requests.
+func SetAccessControlAllowHeaders(w http.ResponseWriter, origin string) {
+	// Access-Control-Allow-Origin can't be '*' with requests that send credentials.
+	// Instead, we need to explicitly set the domain (from request's Origin header)
+	//
+	// Allow requests from anyone's localhost and only from secure pages.
+	if strings.HasPrefix(origin, "http://localhost:") || strings.HasPrefix(origin, "https://") {
+		w.Header().Set("Access-Control-Allow-Origin", origin)
+		w.Header().Set("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE,OPTIONS")
+		w.Header().Set("Access-Control-Allow-Headers", "Cookie,X-User-Id,X-Request-Id,Content-Type")
+		w.Header().Set("Access-Control-Allow-Credentials", "true")
+	}
+}
+
+// GetRequestID returns the Moov header value for request IDs
+func GetRequestID(r *http.Request) string {
+	return r.Header.Get("X-Request-Id")
+}
diff --git a/pkg/watchman/watchman.go b/pkg/watchman/watchman.go
index 2f870a6..94d9958 100644
--- a/pkg/watchman/watchman.go
+++ b/pkg/watchman/watchman.go
@@ -14,7 +14,7 @@ import (
 	"github.com/moov-io/base/k8s"
 	watchman "github.com/moov-io/watchman/client"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 type Client interface {
@@ -140,13 +140,13 @@ func (c *moovWatchmanClient) Search(ctx context.Context, name string, requestID
 	// Take an Alt and find the SDN for it if that was the highest match
 	if len(search.SDNs) == 0 && len(search.AltNames) > 0 {
 		alt := search.AltNames[0]
-		c.logger.Log("watchman", fmt.Sprintf("Found AltName=%s,SDN=%s with no higher matched SDNs", alt.AlternateID, alt.EntityID), "requestID", requestID)
+		c.logger.Log(fmt.Sprintf("Found AltName=%s,SDN=%s with no higher matched SDNs", alt.AlternateID, alt.EntityID))
 		return c.altToSDN(ctx, search.AltNames[0], requestID)
 	}
 	// AltName matched higher than SDN names, so return the SDN of the matched AltName
 	if len(search.SDNs) > 0 && len(search.AltNames) > 0 && (search.AltNames[0].Match > 0.1) && search.AltNames[0].Match > search.SDNs[0].Match {
 		alt := search.AltNames[0]
-		c.logger.Log("watchman", fmt.Sprintf("AltName=%s,SDN=%s had higher match than SDN=%s", alt.AlternateID, alt.EntityID, search.SDNs[0].EntityID), "requestID", requestID)
+		c.logger.Log(fmt.Sprintf("AltName=%s,SDN=%s had higher match than SDN=%s", alt.AlternateID, alt.EntityID, search.SDNs[0].EntityID))
 		return c.altToSDN(ctx, alt, requestID)
 	}
 	// Return the SDN as Alts matched lower
@@ -174,7 +174,8 @@ func NewClient(logger log.Logger, endpoint string, debug bool) Client {
 		conf.BasePath = endpoint // override from provided Watchman_ENDPOINT env variable
 	}
 
-	logger.Log("watchman", fmt.Sprintf("using %s for Watchman address", conf.BasePath))
+	logger = logger.WithKeyValue("package", "watchman")
+	logger.Log(fmt.Sprintf("using %s for Watchman address", conf.BasePath))
 
 	return &moovWatchmanClient{
 		underlying: watchman.NewAPIClient(conf),


Test patch:
diff --git a/cmd/server/main_test.go b/cmd/server/main_test.go
index 9e32153..7f0e036 100644
--- a/cmd/server/main_test.go
+++ b/cmd/server/main_test.go
@@ -8,8 +8,8 @@ import (
 	"os"
 	"testing"
 
-	"github.com/go-kit/kit/log"
 	"github.com/moov-io/base/admin"
+	"github.com/moov-io/base/log"
 	"github.com/moov-io/customers/pkg/validator"
 	"github.com/stretchr/testify/require"
 )
diff --git a/internal/database/database_test.go b/internal/database/database_test.go
index 567bf15..0c40674 100644
--- a/internal/database/database_test.go
+++ b/internal/database/database_test.go
@@ -8,7 +8,7 @@ import (
 	"errors"
 	"testing"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func TestNewDataBase__MYSQL(t *testing.T) {
diff --git a/internal/database/mysql_test.go b/internal/database/mysql_test.go
index 9ab98b2..de521dd 100644
--- a/internal/database/mysql_test.go
+++ b/internal/database/mysql_test.go
@@ -8,7 +8,7 @@ import (
 	"errors"
 	"testing"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func TestMySQL__basic(t *testing.T) {
diff --git a/internal/database/sqlite_test.go b/internal/database/sqlite_test.go
index d20043b..3126584 100644
--- a/internal/database/sqlite_test.go
+++ b/internal/database/sqlite_test.go
@@ -9,7 +9,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func TestSQLite__basic(t *testing.T) {
diff --git a/pkg/accounts/repository_test.go b/pkg/accounts/repository_test.go
index 91bf0c4..180fb3f 100644
--- a/pkg/accounts/repository_test.go
+++ b/pkg/accounts/repository_test.go
@@ -15,7 +15,7 @@ import (
 	"github.com/moov-io/customers/pkg/customers"
 	"github.com/moov-io/customers/pkg/secrets"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 type testAccountRepository struct {
diff --git a/pkg/accounts/router_test.go b/pkg/accounts/router_test.go
index a7eff30..64c5323 100644
--- a/pkg/accounts/router_test.go
+++ b/pkg/accounts/router_test.go
@@ -26,8 +26,8 @@ import (
 	"github.com/moov-io/customers/pkg/validator/testvalidator"
 	"github.com/moov-io/customers/pkg/watchman"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
diff --git a/pkg/accounts/validate_test.go b/pkg/accounts/validate_test.go
index 3f76208..c419d77 100644
--- a/pkg/accounts/validate_test.go
+++ b/pkg/accounts/validate_test.go
@@ -25,8 +25,8 @@ import (
 	"github.com/moov-io/customers/pkg/validator/microdeposits"
 	"github.com/moov-io/customers/pkg/validator/testvalidator"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 func TestRouter__AccountValidation(t *testing.T) {
diff --git a/pkg/configuration/router_test.go b/pkg/configuration/router_test.go
index eccaf13..ede12df 100644
--- a/pkg/configuration/router_test.go
+++ b/pkg/configuration/router_test.go
@@ -20,8 +20,8 @@ import (
 	"github.com/moov-io/customers/pkg/client"
 	"github.com/moov-io/customers/pkg/documents/storage"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 	"github.com/stretchr/testify/require"
 )
 
diff --git a/pkg/customers/address_test.go b/pkg/customers/address_test.go
index b03e967..0ec89f1 100644
--- a/pkg/customers/address_test.go
+++ b/pkg/customers/address_test.go
@@ -8,8 +8,8 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 	"github.com/stretchr/testify/require"
 
 	"github.com/moov-io/customers/pkg/client"
diff --git a/pkg/customers/approval_ofac_test.go b/pkg/customers/approval_ofac_test.go
index 3fd8ae8..4fd8535 100644
--- a/pkg/customers/approval_ofac_test.go
+++ b/pkg/customers/approval_ofac_test.go
@@ -12,9 +12,9 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
 	"github.com/moov-io/base"
+	"github.com/moov-io/base/log"
 	"github.com/moov-io/customers/pkg/client"
 	"github.com/moov-io/customers/pkg/watchman"
 	watchmanClient "github.com/moov-io/watchman/client"
diff --git a/pkg/customers/approval_test.go b/pkg/customers/approval_test.go
index 356a644..9bbcaf9 100644
--- a/pkg/customers/approval_test.go
+++ b/pkg/customers/approval_test.go
@@ -17,7 +17,7 @@ import (
 
 	"github.com/moov-io/customers/pkg/client"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func TestCustomers__updateCustomerStatus(t *testing.T) {
diff --git a/pkg/customers/customer_search_scope_test.go b/pkg/customers/customer_search_scope_test.go
index 8e7689b..1286399 100644
--- a/pkg/customers/customer_search_scope_test.go
+++ b/pkg/customers/customer_search_scope_test.go
@@ -5,9 +5,9 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	"github.com/go-kit/kit/log"
 	fuzz "github.com/google/gofuzz"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 	"github.com/stretchr/testify/require"
 
 	"github.com/moov-io/customers/pkg/client"
diff --git a/pkg/customers/customer_search_test.go b/pkg/customers/customer_search_test.go
index 99979d8..9433d7c 100644
--- a/pkg/customers/customer_search_test.go
+++ b/pkg/customers/customer_search_test.go
@@ -11,8 +11,8 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 
 	"github.com/moov-io/customers/internal/database"
 	"github.com/moov-io/customers/pkg/client"
diff --git a/pkg/customers/customer_ssn_test.go b/pkg/customers/customer_ssn_test.go
index 141cf1f..dbe5cc7 100644
--- a/pkg/customers/customer_ssn_test.go
+++ b/pkg/customers/customer_ssn_test.go
@@ -11,8 +11,8 @@ import (
 	"github.com/moov-io/customers/internal/database"
 	"github.com/moov-io/customers/pkg/secrets"
 
-	"github.com/go-kit/kit/log"
 	"github.com/moov-io/base"
+	"github.com/moov-io/base/log"
 )
 
 var (
diff --git a/pkg/customers/customers_test.go b/pkg/customers/customers_test.go
index 0f372be..bfe905f 100644
--- a/pkg/customers/customers_test.go
+++ b/pkg/customers/customers_test.go
@@ -23,8 +23,8 @@ import (
 
 	"github.com/moov-io/customers/pkg/client"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 var _ CustomerRepository = (*testCustomerRepository)(nil)
diff --git a/pkg/documents/disclaimers_test.go b/pkg/documents/disclaimers_test.go
index 3902a98..ae7ca5e 100644
--- a/pkg/documents/disclaimers_test.go
+++ b/pkg/documents/disclaimers_test.go
@@ -20,8 +20,8 @@ import (
 	"github.com/moov-io/customers/internal/database"
 	"github.com/moov-io/customers/pkg/client"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 type testDisclaimerRepository struct {
diff --git a/pkg/documents/documents_test.go b/pkg/documents/documents_test.go
index da55bfb..30ab5fd 100644
--- a/pkg/documents/documents_test.go
+++ b/pkg/documents/documents_test.go
@@ -29,8 +29,8 @@ import (
 	"github.com/moov-io/customers/pkg/documents/storage"
 	"github.com/moov-io/customers/pkg/secrets"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 )
 
 type testDocumentRepository struct {
diff --git a/pkg/documents/repository_test.go b/pkg/documents/repository_test.go
index 72ed47f..588ebb9 100644
--- a/pkg/documents/repository_test.go
+++ b/pkg/documents/repository_test.go
@@ -12,9 +12,9 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
 	"github.com/moov-io/base"
+	"github.com/moov-io/base/log"
 	"github.com/moov-io/customers/internal/database"
 	"github.com/moov-io/customers/pkg/client"
 	"github.com/moov-io/customers/pkg/customers"
diff --git a/pkg/documents/storage/bucket_test.go b/pkg/documents/storage/bucket_test.go
index be9e29a..1775c85 100644
--- a/pkg/documents/storage/bucket_test.go
+++ b/pkg/documents/storage/bucket_test.go
@@ -9,7 +9,7 @@ import (
 	"io/ioutil"
 	"testing"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func TestBucket__openBucket(t *testing.T) {
diff --git a/pkg/documents/storage/files_test.go b/pkg/documents/storage/files_test.go
index 3ec349c..294d31a 100644
--- a/pkg/documents/storage/files_test.go
+++ b/pkg/documents/storage/files_test.go
@@ -15,8 +15,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
+	"github.com/moov-io/base/log"
 	"gocloud.dev/blob"
 )
 
diff --git a/pkg/documents/storage/test_bucket.go b/pkg/documents/storage/test_bucket.go
index 88d4953..b87e695 100644
--- a/pkg/documents/storage/test_bucket.go
+++ b/pkg/documents/storage/test_bucket.go
@@ -9,7 +9,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 	"gocloud.dev/blob"
 	"gocloud.dev/blob/fileblob"
 )
diff --git a/pkg/fed/client_test.go b/pkg/fed/client_test.go
index b4b93a5..2d39739 100644
--- a/pkg/fed/client_test.go
+++ b/pkg/fed/client_test.go
@@ -9,7 +9,7 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 )
 
 func TestFED(t *testing.T) {
diff --git a/pkg/paygate/client_test.go b/pkg/paygate/client_test.go
index fa686d1..47b672f 100644
--- a/pkg/paygate/client_test.go
+++ b/pkg/paygate/client_test.go
@@ -16,7 +16,7 @@ import (
 	"github.com/moov-io/base/docker"
 	"github.com/moov-io/paygate/pkg/config"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 	"github.com/ory/dockertest/v3"
 	"gopkg.in/yaml.v2"
 )
diff --git a/pkg/reports/router_test.go b/pkg/reports/router_test.go
index 5604575..e8f5593 100644
--- a/pkg/reports/router_test.go
+++ b/pkg/reports/router_test.go
@@ -8,9 +8,9 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/go-kit/kit/log"
 	"github.com/gorilla/mux"
 	"github.com/moov-io/base"
+	"github.com/moov-io/base/log"
 	"github.com/stretchr/testify/require"
 
 	"github.com/moov-io/customers/internal/database"
diff --git a/pkg/watchman/watchman_test.go b/pkg/watchman/watchman_test.go
index 451d0eb..de638e8 100644
--- a/pkg/watchman/watchman_test.go
+++ b/pkg/watchman/watchman_test.go
@@ -16,7 +16,7 @@ import (
 	"github.com/moov-io/base/docker"
 	watchman "github.com/moov-io/watchman/client"
 
-	"github.com/go-kit/kit/log"
+	"github.com/moov-io/base/log"
 	"github.com/ory/dockertest/v3"
 )