diff --git a/cmd/add.go b/cmd/add.go
index 86aad0c206ff81b0554bfd436421592d1fd568e7..4085fbe323b5d3977b558636a195c052303f96cf 100644
--- a/cmd/add.go
+++ b/cmd/add.go
@@ -18,14 +18,15 @@ package cmd
 import (
 	"context"
 	"fmt"
+	"io/ioutil"
+	"os"
+	"time"
+
 	"github.com/google/trillian"
+	"github.com/lukehinds/rekor/log"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 	"google.golang.org/grpc"
-	"io/ioutil"
-	"log"
-	"os"
-	"time"
 )
 
 //type LeafData struct {
@@ -71,6 +72,7 @@ var addCmd = &cobra.Command{
 For more information, visit [domain]`,
 
 	Run: func(cmd *cobra.Command, args []string) {
+		log := log.Logger
 		logRpcServer := viper.GetString("log_rpc_server")
 		tLogID := viper.GetInt64("tlog_id")
 		linkfile := viper.GetString("linkfile")
@@ -82,7 +84,7 @@ For more information, visit [domain]`,
 		// Set up and test connection to rpc server
 		conn, err := grpc.DialContext(ctx, logRpcServer, grpc.WithInsecure())
 		if err != nil {
-			fmt.Println("Failed to connect to log server:", err)
+			log.Error("Failed to connect to log server:", err)
 		}
 		defer conn.Close()
 
@@ -101,8 +103,8 @@ For more information, visit [domain]`,
 
 		resp := &Response{}
 
-		resp, err =  server.addLeaf(byteValue, tLogID)
-		log.Printf("Server PUT Response: %s", resp.status)
+		resp, err = server.addLeaf(byteValue, tLogID)
+		log.Infof("Server PUT Response: %s", resp.status)
 	},
 }
 
diff --git a/cmd/get.go b/cmd/get.go
index d2ad32401d50d676ede7a8eeb9dc902106e15e9b..be3ed54a8a256a1c2c2ebf5c6c0fac170eaeba29 100644
--- a/cmd/get.go
+++ b/cmd/get.go
@@ -18,14 +18,15 @@ package cmd
 import (
 	"context"
 	"fmt"
-	"github.com/google/trillian"
-	"github.com/spf13/viper"
-	"google.golang.org/grpc"
 	"io/ioutil"
-	"log"
 	"os"
 	"time"
 
+	"github.com/google/trillian"
+	"github.com/lukehinds/rekor/log"
+	"github.com/spf13/viper"
+	"google.golang.org/grpc"
+
 	"github.com/spf13/cobra"
 )
 
@@ -37,6 +38,7 @@ var getCmd = &cobra.Command{
 
 For more information, visit [domain]`,
 	Run: func(cmd *cobra.Command, args []string) {
+		log := log.Logger
 		logRpcServer := viper.GetString("log_rpc_server")
 		tLogID := viper.GetInt64("tlog_id")
 		linkfile := viper.GetString("linkfile")
@@ -46,7 +48,7 @@ For more information, visit [domain]`,
 
 		conn, err := grpc.DialContext(ctx, logRpcServer, grpc.WithInsecure())
 		if err != nil {
-			fmt.Println("Failed to connect to log server:", err)
+			log.Errorf("Failed to connect to log server:", err)
 		}
 		defer conn.Close()
 
@@ -61,8 +63,8 @@ For more information, visit [domain]`,
 		server := serverInstance(tLogClient, tLogID)
 
 		resp := &Response{}
-		resp, err =  server.getLeaf(byteValue, tLogID)
-		log.Printf("Server GET Response: %s", resp.status)
+		resp, err = server.getLeaf(byteValue, tLogID)
+		log.Infof("Server GET Response: %s", resp.status)
 	},
 }
 
diff --git a/cmd/inclusion.go b/cmd/inclusion.go
index 6f1b39169fe7b260701be1af3c4db05341ae7fa7..b8b7f2d671b802d15b87b89a1e112bb5647c13f1 100644
--- a/cmd/inclusion.go
+++ b/cmd/inclusion.go
@@ -19,11 +19,11 @@ import (
 	"context"
 	"fmt"
 	"io/ioutil"
-	"log"
 	"os"
 	"time"
 
 	"github.com/google/trillian"
+	"github.com/lukehinds/rekor/log"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 	"google.golang.org/grpc"
@@ -37,6 +37,7 @@ var inclusionCmd = &cobra.Command{
 
 For more information, visit [domain]`,
 	Run: func(cmd *cobra.Command, args []string) {
+		log := log.Logger
 		logRpcServer := viper.GetString("log_rpc_server")
 		tLogID := viper.GetInt64("tlog_id")
 		linkfile := viper.GetString("linkfile")
@@ -47,7 +48,7 @@ For more information, visit [domain]`,
 		// Set up and test connection to rpc server
 		conn, err := grpc.DialContext(ctx, logRpcServer, grpc.WithInsecure())
 		if err != nil {
-			fmt.Println("Failed to connect to log server:", err)
+			log.Fatal("Failed to connect to log server:", err)
 		}
 		defer conn.Close()
 
@@ -67,7 +68,7 @@ For more information, visit [domain]`,
 		resp := &Response{}
 
 		resp, err = server.getInclusion(byteValue, tLogID)
-		log.Printf("Server PUT Response: %s", resp)
+		log.Infof("Server PUT Response: %s", resp)
 	},
 }
 
diff --git a/cmd/log_server.go b/cmd/log_server.go
index 5673634c3e32dd413a809f1245069136d3022796..3b4460399575aa60017a1660eb710e6de3b72a53 100644
--- a/cmd/log_server.go
+++ b/cmd/log_server.go
@@ -19,16 +19,16 @@ package cmd
 import (
 	"context"
 	"fmt"
-	"log"
 	"time"
 
+	"github.com/lukehinds/rekor/log"
+
 	"github.com/google/trillian"
 	"github.com/google/trillian/client"
 	"github.com/google/trillian/merkle"
 	"github.com/google/trillian/merkle/rfc6962"
 	"github.com/google/trillian/types"
 	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/status"
 )
 
 type server struct {
@@ -43,11 +43,6 @@ type Response struct {
 	leafhash string
 }
 
-type InclusionResponse struct {
-	status   string
-	leafhash string
-}
-
 func serverInstance(client trillian.TrillianLogClient, tLogID int64) *server {
 	return &server{
 		client: client,
@@ -71,7 +66,7 @@ func (s *server) root() (types.LogRootV1, error) {
 }
 
 func (s *server) getInclusion(byteValue []byte, tLogID int64) (*Response, error) {
-
+	log := log.Logger
 	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
 	defer cancel()
 
@@ -80,7 +75,7 @@ func (s *server) getInclusion(byteValue []byte, tLogID int64) (*Response, error)
 		return &Response{}, err
 	}
 
-	log.Printf("[server:wait] Root hash: %x", root.RootHash)
+	log.Info("Root hash: %x", root.RootHash)
 
 	hasher := rfc6962.DefaultHasher
 	leafHash := hasher.HashLeaf(byteValue)
@@ -91,36 +86,39 @@ func (s *server) getInclusion(byteValue []byte, tLogID int64) (*Response, error)
 			LeafHash: leafHash,
 			TreeSize: int64(root.TreeSize),
 		})
+
 	if err != nil {
-		fmt.Println("one")
-		return nil, status.Errorf(codes.Internal, "failed to get inclusion proof: %v", err)
+		log.Error(codes.Internal, "failed to get inclusion proof: %v", err)
+		return &Response{}, nil
 	}
 	if err != nil {
-		fmt.Println("two")
+		log.Info("two")
 		return &Response{}, err
 	}
 	if len(resp.Proof) < 1 {
-		fmt.Println("three")
+		log.Info("three")
 		return &Response{}, nil
 	}
 
 	v := merkle.NewLogVerifier(rfc6962.DefaultHasher)
+
 	for i, proof := range resp.Proof {
 		hashes := proof.GetHashes()
 		for j, hash := range hashes {
-			log.Printf("Proof[%d],hash[%d] == %x\n", i, j, hash)
+			log.Infof("Proof[%d],hash[%d] == %x\n", i, j, hash)
 		}
 		if err := v.VerifyInclusionProof(proof.LeafIndex, int64(root.TreeSize), hashes, root.RootHash, leafHash); err != nil {
 			return &Response{}, err
 		}
 	}
+
 	return &Response{
-		status: "ok",
+		status: "OK",
 	}, nil
 }
 
 func (s *server) addLeaf(byteValue []byte, tLogID int64) (*Response, error) {
-
+	log := log.Logger
 	leaf := &trillian.LogLeaf{
 		LeafValue: byteValue,
 	}
@@ -135,12 +133,12 @@ func (s *server) addLeaf(byteValue []byte, tLogID int64) (*Response, error) {
 
 	c := codes.Code(resp.QueuedLeaf.GetStatus().GetCode())
 	if c != codes.OK && c != codes.AlreadyExists {
-		fmt.Errorf("Server Status: Bad status: %v", resp.QueuedLeaf.GetStatus())
+		log.Error("Server Status: Bad status: %v", resp.QueuedLeaf.GetStatus())
 	}
 	if c == codes.OK {
-		log.Println("Server status: ok")
+		log.Info("Server status: ok")
 	} else if c == codes.AlreadyExists {
-		log.Printf("Data already Exists")
+		log.Error("Data already Exists")
 	}
 
 	return &Response{
@@ -149,7 +147,7 @@ func (s *server) addLeaf(byteValue []byte, tLogID int64) (*Response, error) {
 }
 
 func (s *server) getLeaf(byteValue []byte, tlog_id int64) (*Response, error) {
-
+	log := log.Logger
 	hasher := rfc6962.DefaultHasher
 	leafHash := hasher.HashLeaf(byteValue)
 
@@ -165,10 +163,10 @@ func (s *server) getLeaf(byteValue []byte, tlog_id int64) (*Response, error) {
 
 	for i, logLeaf := range resp.GetLeaves() {
 		leafValue := logLeaf.GetLeafValue()
-		log.Printf("[server:get] %d: %s", i, leafValue)
+		log.Infof("[server:get] %d: %s", i, leafValue)
 	}
 
 	return &Response{
-		status: "ok",
+		status: "OK",
 	}, nil
 }
diff --git a/go.mod b/go.mod
index 7a75e53ab9be5110fae3457bbc735f1df41191be..c9d6b3a284b284dd661fc71a36fe66eee08ad6e6 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,10 @@ go 1.14
 require (
 	github.com/google/trillian v1.3.8
 	github.com/mitchellh/go-homedir v1.1.0
+	github.com/sirupsen/logrus v1.4.2
 	github.com/spf13/cobra v1.0.0
 	github.com/spf13/viper v1.7.0
+	github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
+	go.uber.org/zap v1.13.0
 	google.golang.org/grpc v1.25.1
 )
diff --git a/go.sum b/go.sum
index 5bcb33158e8db9a394e8d9b5de2b8c2dfc626600..2a0a42e15586d11a6c69c3c5b369e1da4858f738 100644
--- a/go.sum
+++ b/go.sum
@@ -35,6 +35,9 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@@ -326,6 +329,7 @@ github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOms
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@@ -362,6 +366,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
+github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
 github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
@@ -386,13 +392,16 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E=
 go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
 go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
diff --git a/log/log.go b/log/log.go
new file mode 100644
index 0000000000000000000000000000000000000000..1847aee858c85e57f8dab74ec7a5069501ac6a70
--- /dev/null
+++ b/log/log.go
@@ -0,0 +1,21 @@
+package log
+
+import (
+	"log"
+
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+var Logger = createGlobalLogger()
+
+func createGlobalLogger() *zap.SugaredLogger {
+	cfg := zap.NewDevelopmentConfig()
+	cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
+	logger, err := cfg.Build()
+	if err != nil {
+		log.Fatalln("createLogger", err.Error)
+	}
+
+	return logger.Sugar()
+}