sklog - Add CloudLogger implementation that uses slog.Logger.

Also updates perf-tool to use that implementation.

Next CL will add logger.Logger as a common.Opt.

Change-Id: Ic3dbf3fbc5389a9a41eb9df5f36bc3eb545b9af8
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/220516
Commit-Queue: Joe Gregorio <jcgregorio@google.com>
Reviewed-by: Joe Gregorio <jcgregorio@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/go.mod b/go.mod
index 42df4e2..6f6662a 100644
--- a/go.mod
+++ b/go.mod
@@ -61,7 +61,7 @@
 	github.com/huandu/xstrings v1.2.0 // indirect
 	github.com/huin/goserial v0.0.0-20121012073615-7b90efdb22b1
 	github.com/imdario/mergo v0.3.7 // indirect
-	github.com/jcgregorio/logger v0.0.0-20190528172559-6fef4ed9e5a9
+	github.com/jcgregorio/logger v0.1.2
 	github.com/jcgregorio/slog v0.0.0-20190423190439-e6f2d537f900
 	github.com/jmoiron/sqlx v1.2.0
 	github.com/kisielk/errcheck v1.2.0 // indirect
diff --git a/go.sum b/go.sum
index b5e7831..eac0bfa 100644
--- a/go.sum
+++ b/go.sum
@@ -275,6 +275,10 @@
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/jcgregorio/logger v0.0.0-20190528172559-6fef4ed9e5a9 h1:NuEHvfu3DDXJkOSjRSqGTDfh86VvD7bfDoctxNngs3g=
 github.com/jcgregorio/logger v0.0.0-20190528172559-6fef4ed9e5a9/go.mod h1:a1MmUykXJr+dI02wwT/CcnJbflFsX/sHP1bAKRPZFsU=
+github.com/jcgregorio/logger v0.1.0 h1:CUpKwiuX2KoSieInj+NgOPxKNb9+G0NHBOrEX19XV5Y=
+github.com/jcgregorio/logger v0.1.0/go.mod h1:a1MmUykXJr+dI02wwT/CcnJbflFsX/sHP1bAKRPZFsU=
+github.com/jcgregorio/logger v0.1.2 h1:kHiF857oOObzlUer5ANZ95U08A7k2INjivnss4IyMCg=
+github.com/jcgregorio/logger v0.1.2/go.mod h1:a1MmUykXJr+dI02wwT/CcnJbflFsX/sHP1bAKRPZFsU=
 github.com/jcgregorio/slog v0.0.0-20190423190439-e6f2d537f900 h1:H8hiPQr5PtkrB5z3Do/9iR5tEwuAFNim68cqcoAlHeY=
 github.com/jcgregorio/slog v0.0.0-20190423190439-e6f2d537f900/go.mod h1:YT3uVwwZ2P4vmZcM3xICUNJ6dqBwoiSgVAqxHu3rcoo=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
diff --git a/go/sklog/slog.go b/go/sklog/slog.go
new file mode 100644
index 0000000..abe1ab4
--- /dev/null
+++ b/go/sklog/slog.go
@@ -0,0 +1,78 @@
+package sklog
+
+import (
+	"os"
+
+	_logger "github.com/jcgregorio/logger"
+	"github.com/jcgregorio/slog"
+)
+
+// CloudLoggerSLogImpl implements CloudLogger using slog.Logger.
+type CloudLoggerSLogImpl struct {
+	stdLog slog.Logger
+}
+
+// NewSLogCloudLogger returns a CloudLoggerSLogImpl that uses the given slog.Logger.
+func NewSLogCloudLogger(l slog.Logger) *CloudLoggerSLogImpl {
+	return &CloudLoggerSLogImpl{
+		stdLog: l,
+	}
+}
+
+// SLogLogMode is the mode logging enum type.
+type SLogLogMode int
+
+// Types of logging that NewSLogLogger supports.
+const (
+	SLogNone SLogLogMode = iota
+	SLogStderr
+)
+
+// NewSLogLogger creates a new CloudLoggerSLogImpl that either logs to stderr, or does
+// no logging, depending upon the value of mode. It uses github.com/jcgregorio/logger
+// to implement the slog.Logger interface.
+//
+// The return value implements CloudLogger.
+//
+// Usage:
+//
+//			sklog.SetLogger(sklog.NewStdErrCloudLogger(logToStdErr))
+//
+func NewStdErrCloudLogger(mode SLogLogMode) *CloudLoggerSLogImpl {
+	if mode == SLogStderr {
+		return NewSLogCloudLogger(_logger.NewFromOptions(&_logger.Options{SyncWriter: os.Stderr}))
+	} else {
+		return NewSLogCloudLogger(_logger.NewNopLogger())
+	}
+}
+
+// See CloudLogger.
+func (c *CloudLoggerSLogImpl) CloudLog(reportName string, payload *LogPayload) {
+	switch payload.Severity {
+	case DEBUG:
+		c.stdLog.Debug(payload.Payload)
+	case INFO, NOTICE:
+		c.stdLog.Info(payload.Payload)
+	case WARNING:
+		c.stdLog.Warning(payload.Payload)
+	case ERROR:
+		c.stdLog.Error(payload.Payload)
+	case CRITICAL, ALERT:
+		c.stdLog.Fatal(payload.Payload)
+	}
+}
+
+// See CloudLogger.
+func (c *CloudLoggerSLogImpl) BatchCloudLog(reportName string, payloads ...*LogPayload) {
+	for _, payload := range payloads {
+		c.CloudLog(reportName, payload)
+	}
+}
+
+// See CloudLogger.
+func (c *CloudLoggerSLogImpl) Flush() {
+	_ = os.Stdout.Sync()
+}
+
+// Assert that we implement the ClougLogger interface:
+var _ CloudLogger = (*CloudLoggerSLogImpl)(nil)
diff --git a/perf/go/perf-tool/main.go b/perf/go/perf-tool/main.go
index e8630b0..ecdc440 100644
--- a/perf/go/perf-tool/main.go
+++ b/perf/go/perf-tool/main.go
@@ -8,8 +8,6 @@
 	"os"
 
 	"cloud.google.com/go/bigtable"
-	"github.com/jcgregorio/logger"
-	"github.com/jcgregorio/slog"
 	"github.com/spf13/cobra"
 	"go.skia.org/infra/go/auth"
 	"go.skia.org/infra/go/query"
@@ -22,53 +20,6 @@
 	store *btts.BigTableTraceStore
 )
 
-// TODO(jcgregorio) Migrate this into its own module that we can use everywhere
-// once we're happy with the design.
-//
-// cloudLoggerImpl implements sklog.CloudLogger.
-type cloudLoggerImpl struct {
-	stdLog slog.Logger
-}
-
-// newLogger creates a new cloudLoggerImpl that either logs to stdout, or does
-// no logging, depending upon the value of enable.
-func newLogger(enable bool) *cloudLoggerImpl {
-	if enable {
-		return &cloudLoggerImpl{
-			stdLog: logger.NewFromOptions(&logger.Options{SyncWriter: os.Stderr}),
-		}
-	} else {
-		return &cloudLoggerImpl{
-			stdLog: logger.NewNopLogger(),
-		}
-	}
-}
-
-func (c *cloudLoggerImpl) CloudLog(reportName string, payload *sklog.LogPayload) {
-	switch payload.Severity {
-	case sklog.DEBUG:
-		c.stdLog.Debug(payload.Payload)
-	case sklog.INFO, sklog.NOTICE:
-		c.stdLog.Info(payload.Payload)
-	case sklog.WARNING:
-		c.stdLog.Warning(payload.Payload)
-	case sklog.ERROR:
-		c.stdLog.Error(payload.Payload)
-	case sklog.CRITICAL, sklog.ALERT:
-		c.stdLog.Fatal(payload.Payload)
-	}
-}
-
-func (c *cloudLoggerImpl) BatchCloudLog(reportName string, payloads ...*sklog.LogPayload) {
-	for _, payload := range payloads {
-		c.CloudLog(reportName, payload)
-	}
-}
-
-func (c *cloudLoggerImpl) Flush() {
-	_ = os.Stdout.Sync()
-}
-
 // flags
 var (
 	logToStdErr    bool
@@ -83,7 +34,11 @@
 	cmd := cobra.Command{
 		Use: "perf-tool [sub]",
 		PersistentPreRunE: func(c *cobra.Command, args []string) error {
-			sklog.SetLogger(newLogger(logToStdErr))
+			logMode := sklog.SLogNone
+			if logToStdErr {
+				logMode = sklog.SLogStderr
+			}
+			sklog.SetLogger(sklog.NewStdErrCloudLogger(logMode))
 
 			ts, err := auth.NewDefaultTokenSource(true, bigtable.Scope)
 			if err != nil {