Skip to content

Commit

Permalink
Add migration logger (#2698)
Browse files Browse the repository at this point in the history
- introduce simple logger in migration internal package
- unit tests
- integrate into main function
  • Loading branch information
ZenGround0 authored May 2, 2019
1 parent 1511955 commit 83faad9
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 8 deletions.
47 changes: 47 additions & 0 deletions tools/migration/internal/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package internal

import (
"io"
"log"
"os"
)

// Logger logs migration events to disk and, if initialized with verbose,
// stdout too.
type Logger struct {
closer io.WriteCloser
logger *log.Logger
}

// NewLogger creates a new Logger. All log writes go to f, the logging file.
// If the verbose flag is true all log writes also go to stdout.
func NewLogger(wc io.WriteCloser, verbose bool) *Logger {
// by default just write to file
var w io.Writer
w = wc
if verbose {
w = io.MultiWriter(wc, os.Stdout)
}
return &Logger{
closer: wc,
logger: log.New(w, "", 0),
}
}

// Error logs an error to the logging output.
func (l *Logger) Error(err error) {
if err == nil {
return
}
l.logger.Printf("ERROR: %s", err.Error())
}

// Print logs a string to the logging output.
func (l *Logger) Print(msg string) {
l.logger.Print(msg)
}

// Close closes the logfile backing the Logger.
func (l *Logger) Close() error {
return l.closer.Close()
}
75 changes: 75 additions & 0 deletions tools/migration/internal/logger_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package internal_test

import (
"errors"
"fmt"
"io/ioutil"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

. "github.com/filecoin-project/go-filecoin/tools/migration/internal"
)

func TestLoggerWritesToFile(t *testing.T) {
f, err := ioutil.TempFile("", "logfile")
require.NoError(t, err)
defer func() {
require.NoError(t, os.Remove(f.Name()))
}()

logger := NewLogger(f, false)
logger.Print("testing print 1")
errTest := errors.New("testing error 2")
logger.Error(errTest)

// Reopen file so we can read new writes
out, err := ioutil.ReadFile(f.Name())
require.NoError(t, err)
outStr := string(out)
assert.Contains(t, outStr, "testing print 1")
expectedErrStr := fmt.Sprintf("ERROR: %s", errTest.Error())
assert.Contains(t, outStr, expectedErrStr)
}

func TestLoggerWritesToBothVerbose(t *testing.T) {
// Point os.Stdout to a temp file
fStdout, err := ioutil.TempFile("", "stdout")
require.NoError(t, err)
defer func() {
require.NoError(t, os.Remove(fStdout.Name()))
}()
old := os.Stdout
os.Stdout = fStdout
defer func() { os.Stdout = old }()

// Create log file
fLogFile, err := ioutil.TempFile("", "logfile")
require.NoError(t, err)
defer func() {
require.NoError(t, os.Remove(fLogFile.Name()))
}()

// Log verbosely
logger := NewLogger(fLogFile, true)
logger.Print("test line")
errTest := errors.New("test err")
logger.Error(errTest)
expectedErrStr := fmt.Sprintf("ERROR: %s", errTest.Error())

// Check logfile
outLogFile, err := ioutil.ReadFile(fLogFile.Name())
require.NoError(t, err)
outLogFileStr := string(outLogFile)
assert.Contains(t, outLogFileStr, "test line")
assert.Contains(t, outLogFileStr, expectedErrStr)

// Check stdout alias file
outStdout, err := ioutil.ReadFile(fStdout.Name())
require.NoError(t, err)
outStdoutStr := string(outStdout)
assert.Contains(t, outStdoutStr, "test line")
assert.Contains(t, outStdoutStr, expectedErrStr)
}
9 changes: 5 additions & 4 deletions tools/migration/internal/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ type Migration interface {

// MigrationRunner represent a migration command
type MigrationRunner struct {
verbose bool
logger *Logger
command string
oldRepoOpt string
}

// NewMigrationRunner builds a MirgrationRunner for the given command and repo options
func NewMigrationRunner(verb bool, command, oldRepoOpt string) *MigrationRunner {
func NewMigrationRunner(logger *Logger, command, oldRepoOpt string) *MigrationRunner {
// TODO: Issue #2585 Implement repo migration version detection and upgrade decisioning

return &MigrationRunner{
verbose: verb,
logger: logger,
command: command,
oldRepoOpt: oldRepoOpt,
}
Expand All @@ -47,5 +47,6 @@ func NewMigrationRunner(verb bool, command, oldRepoOpt string) *MigrationRunner
// Run executes the MigrationRunner
func (m *MigrationRunner) Run() error {
// TODO: Issue #2595 Implement first repo migration
return nil

return m.logger.Close()
}
12 changes: 10 additions & 2 deletions tools/migration/internal/runner_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package internal_test

import (
"io/ioutil"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

tf "github.com/filecoin-project/go-filecoin/testhelpers/testflags"
. "github.com/filecoin-project/go-filecoin/tools/migration/internal"
Expand All @@ -12,7 +15,12 @@ import (
// TODO: Issue #2595 Implement first repo migration
func TestMigrationRunner_Run(t *testing.T) {
tf.UnitTest(t)

runner := NewMigrationRunner(false, "describe", "/home/filecoin-symlink")
dummyLogFile, err := ioutil.TempFile("", "logfile")
require.NoError(t, err)
logger := NewLogger(dummyLogFile, false)
defer func() {
require.NoError(t, os.Remove(dummyLogFile.Name()))
}()
runner := NewMigrationRunner(logger, "describe", "/home/filecoin-symlink")
assert.NoError(t, runner.Run())
}
31 changes: 29 additions & 2 deletions tools/migration/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ import (
"os"
"strings"

"github.com/mitchellh/go-homedir"

"github.com/filecoin-project/go-filecoin/tools/migration/internal"
)

const defaultLogFilePath = "~/.filecoin-migration-logs"

// USAGE is the usage of the migration tool
const USAGE = `
USAGE
Expand All @@ -34,6 +38,8 @@ OPTIONS
This message
-v --verbose
Print diagnostic messages to stdout
--log-file
The path of the file for writing detailed log output
EXAMPLES
for a migration from version 1 to 2:
Expand All @@ -60,13 +66,18 @@ func main() { // nolint: deadcode
case "-h", "--help":
showUsageAndExit(0)
case "describe", "buildonly", "migrate", "install":
oldRepoOpt, found := findOpt("old-repo", os.Args)
logFile, err := openLogFile()
if err != nil {
exitErr(err.Error())
}
logger := internal.NewLogger(logFile, getVerbose())

oldRepoOpt, found := findOpt("old-repo", os.Args)
if found == false {
exitErr(fmt.Sprintf("Error: --old-repo is required\n%s\n", USAGE))
}

runner := internal.NewMigrationRunner(getVerbose(), command, oldRepoOpt)
runner := internal.NewMigrationRunner(logger, command, oldRepoOpt)
if err := runner.Run(); err != nil {
exitErr(err.Error())
}
Expand Down Expand Up @@ -97,6 +108,22 @@ func getVerbose() bool {
return res
}

func openLogFile() (*os.File, error) {
path, err := getLogFilePath()
if err != nil {
return nil, err
}
return os.OpenFile(path, os.O_APPEND|os.O_CREATE, 0644)
}

func getLogFilePath() (string, error) {
if logPath, found := findOpt("--log-file", os.Args); found {
return logPath, nil
}

return homedir.Expand(defaultLogFilePath)
}

// findOpt fetches option values.
// returns: string: value of option set with "=". If not set, returns ""
// bool: true if option was found, false if not
Expand Down

0 comments on commit 83faad9

Please sign in to comment.