1
0
mirror of https://github.com/beego/bee.git synced 2025-07-12 09:51:00 +00:00

Implementing the new logging infrastructure

Moved logging to the new logging infrastructure by removing the use of
ColorLog() function. Added more documentation. Also fixed some typos in
comments and function names.
This commit is contained in:
Faissal Elamraoui
2016-11-13 15:14:48 +01:00
parent 0e54238559
commit cf7aef47f0
26 changed files with 421 additions and 525 deletions

View File

@ -16,14 +16,13 @@ package main
import (
"database/sql"
"fmt"
"os"
"os/exec"
"path"
"runtime"
"strconv"
"strings"
"time"
"runtime"
)
var cmdMigrate = &Command{
@ -69,18 +68,20 @@ func runMigration(cmd *Command, args []string) int {
gps := GetGOPATHs()
if len(gps) == 0 {
ColorLog("[ERRO] Fail to start[ %s ]\n", "GOPATH environment variable is not set or empty")
os.Exit(2)
logger.Fatal("GOPATH environment variable is not set or empty")
}
gopath := gps[0]
Debugf("GOPATH: %s", gopath)
// load config
gopath := gps[0]
logger.Debugf("GOPATH: %s", gopath)
// Load the configuration
err := loadConfig()
if err != nil {
ColorLog("[ERRO] Fail to parse bee.json[ %s ]\n", err)
logger.Errorf("Failed to load configuration: %s", err)
}
// getting command line arguments
// Getting command line arguments
if len(args) != 0 {
cmd.Flag.Parse(args[1:])
}
@ -96,31 +97,30 @@ func runMigration(cmd *Command, args []string) int {
mConn = "root:@tcp(127.0.0.1:3306)/test"
}
}
ColorLog("[INFO] Using '%s' as 'driver'\n", mDriver)
ColorLog("[INFO] Using '%s' as 'conn'\n", mConn)
logger.Infof("Using '%s' as 'driver'", mDriver)
logger.Infof("Using '%s' as 'conn'", mConn)
driverStr, connStr := string(mDriver), string(mConn)
if len(args) == 0 {
// run all outstanding migrations
ColorLog("[INFO] Running all outstanding migrations\n")
logger.Info("Running all outstanding migrations")
migrateUpdate(currpath, driverStr, connStr)
} else {
mcmd := args[0]
switch mcmd {
case "rollback":
ColorLog("[INFO] Rolling back the last migration operation\n")
logger.Info("Rolling back the last migration operation")
migrateRollback(currpath, driverStr, connStr)
case "reset":
ColorLog("[INFO] Reseting all migrations\n")
logger.Info("Reseting all migrations")
migrateReset(currpath, driverStr, connStr)
case "refresh":
ColorLog("[INFO] Refreshing all migrations\n")
logger.Info("Refreshing all migrations")
migrateRefresh(currpath, driverStr, connStr)
default:
ColorLog("[ERRO] Command is missing\n")
os.Exit(2)
logger.Fatal("Command is missing")
}
}
ColorLog("[SUCC] Migration successful!\n")
logger.Success("Migration successful!")
return 0
}
@ -146,21 +146,21 @@ func migrateRefresh(currpath, driver, connStr string) {
// migrate generates source code, build it, and invoke the binary who does the actual migration
func migrate(goal, currpath, driver, connStr string) {
dir := path.Join(currpath, "database", "migrations")
dir := path.Join(currpath, "database", "migrations")
postfix := ""
if runtime.GOOS == "windows" {
postfix = ".exe"
}
binary := "m" + postfix
source := binary + ".go"
// connect to database
// Connect to database
db, err := sql.Open(driver, connStr)
if err != nil {
ColorLog("[ERRO] Could not connect to %s: %s\n", driver, connStr)
ColorLog("[ERRO] Error: %v", err.Error())
os.Exit(2)
logger.Fatalf("Could not connect to database using '%s': %s", connStr, err)
}
defer db.Close()
checkForSchemaUpdateTable(db, driver)
latestName, latestTime := getLatestMigration(db, goal)
writeMigrationSourceFile(dir, source, driver, connStr, latestTime, latestName, goal)
@ -175,50 +175,44 @@ func migrate(goal, currpath, driver, connStr string) {
func checkForSchemaUpdateTable(db *sql.DB, driver string) {
showTableSQL := showMigrationsTableSQL(driver)
if rows, err := db.Query(showTableSQL); err != nil {
ColorLog("[ERRO] Could not show migrations table: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not show migrations table: %s", err)
} else if !rows.Next() {
// no migrations table, create anew
// No migrations table, create new ones
createTableSQL := createMigrationsTableSQL(driver)
ColorLog("[INFO] Creating 'migrations' table...\n")
logger.Infof("Creating 'migrations' table...")
if _, err := db.Query(createTableSQL); err != nil {
ColorLog("[ERRO] Could not create migrations table: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not create migrations table: %s", err)
}
}
// checking that migrations table schema are expected
// Checking that migrations table schema are expected
selectTableSQL := selectMigrationsTableSQL(driver)
if rows, err := db.Query(selectTableSQL); err != nil {
ColorLog("[ERRO] Could not show columns of migrations table: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not show columns of migrations table: %s", err)
} else {
for rows.Next() {
var fieldBytes, typeBytes, nullBytes, keyBytes, defaultBytes, extraBytes []byte
if err := rows.Scan(&fieldBytes, &typeBytes, &nullBytes, &keyBytes, &defaultBytes, &extraBytes); err != nil {
ColorLog("[ERRO] Could not read column information: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not read column information: %s", err)
}
fieldStr, typeStr, nullStr, keyStr, defaultStr, extraStr :=
string(fieldBytes), string(typeBytes), string(nullBytes), string(keyBytes), string(defaultBytes), string(extraBytes)
if fieldStr == "id_migration" {
if keyStr != "PRI" || extraStr != "auto_increment" {
ColorLog("[ERRO] Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s\n", keyStr, extraStr)
ColorLog("[HINT] Expecting KEY: PRI, EXTRA: auto_increment\n")
os.Exit(2)
logger.Hint("Expecting KEY: PRI, EXTRA: auto_increment")
logger.Fatalf("Column migration.id_migration type mismatch: KEY: %s, EXTRA: %s", keyStr, extraStr)
}
} else if fieldStr == "name" {
if !strings.HasPrefix(typeStr, "varchar") || nullStr != "YES" {
ColorLog("[ERRO] Column migration.name type mismatch: TYPE: %s, NULL: %s\n", typeStr, nullStr)
ColorLog("[HINT] Expecting TYPE: varchar, NULL: YES\n")
os.Exit(2)
logger.Hint("Expecting TYPE: varchar, NULL: YES")
logger.Fatalf("Column migration.name type mismatch: TYPE: %s, NULL: %s", typeStr, nullStr)
}
} else if fieldStr == "created_at" {
if typeStr != "timestamp" || defaultStr != "CURRENT_TIMESTAMP" {
ColorLog("[ERRO] Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s\n", typeStr, defaultStr)
ColorLog("[HINT] Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP\n")
os.Exit(2)
logger.Hint("Expecting TYPE: timestamp, DEFAULT: CURRENT_TIMESTAMP")
logger.Fatalf("Column migration.timestamp type mismatch: TYPE: %s, DEFAULT: %s", typeStr, defaultStr)
}
}
}
@ -262,26 +256,22 @@ func selectMigrationsTableSQL(driver string) string {
func getLatestMigration(db *sql.DB, goal string) (file string, createdAt int64) {
sql := "SELECT name FROM migrations where status = 'update' ORDER BY id_migration DESC LIMIT 1"
if rows, err := db.Query(sql); err != nil {
ColorLog("[ERRO] Could not retrieve migrations: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not retrieve migrations: %s", err)
} else {
if rows.Next() {
if err := rows.Scan(&file); err != nil {
ColorLog("[ERRO] Could not read migrations in database: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not read migrations in database: %s", err)
}
createdAtStr := file[len(file)-15:]
if t, err := time.Parse("20060102_150405", createdAtStr); err != nil {
ColorLog("[ERRO] Could not parse time: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not parse time: %s", err)
} else {
createdAt = t.Unix()
}
} else {
// migration table has no 'update' record, no point rolling back
if goal == "rollback" {
ColorLog("[ERRO] There is nothing to rollback\n")
os.Exit(2)
logger.Fatal("There is nothing to rollback")
}
file, createdAt = "", 0
}
@ -293,8 +283,7 @@ func getLatestMigration(db *sql.DB, goal string) (file string, createdAt int64)
func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime int64, latestName string, task string) {
changeDir(dir)
if f, err := os.OpenFile(source, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err != nil {
ColorLog("[ERRO] Could not create file: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not create file: %s", err)
} else {
content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1)
content = strings.Replace(content, "{{ConnStr}}", connStr, -1)
@ -302,8 +291,7 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in
content = strings.Replace(content, "{{LatestName}}", latestName, -1)
content = strings.Replace(content, "{{Task}}", task, -1)
if _, err := f.WriteString(content); err != nil {
ColorLog("[ERRO] Could not write to file: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not write to file: %s", err)
}
CloseFile(f)
}
@ -314,7 +302,7 @@ func buildMigrationBinary(dir, binary string) {
changeDir(dir)
cmd := exec.Command("go", "build", "-o", binary)
if out, err := cmd.CombinedOutput(); err != nil {
ColorLog("[ERRO] Could not build migration binary: %s\n", err)
logger.Errorf("Could not build migration binary: %s", err)
formatShellErrOutput(string(out))
removeTempFile(dir, binary)
removeTempFile(dir, binary+".go")
@ -328,7 +316,7 @@ func runMigrationBinary(dir, binary string) {
cmd := exec.Command("./" + binary)
if out, err := cmd.CombinedOutput(); err != nil {
formatShellOutput(string(out))
ColorLog("[ERRO] Could not run migration binary: %s\n", err)
logger.Errorf("Could not run migration binary: %s", err)
removeTempFile(dir, binary)
removeTempFile(dir, binary+".go")
os.Exit(2)
@ -341,8 +329,7 @@ func runMigrationBinary(dir, binary string) {
// It exits the system when encouter an error
func changeDir(dir string) {
if err := os.Chdir(dir); err != nil {
ColorLog("[ERRO] Could not find migration directory: %s\n", err)
os.Exit(2)
logger.Fatalf("Could not find migration directory: %s", err)
}
}
@ -350,7 +337,7 @@ func changeDir(dir string) {
func removeTempFile(dir, file string) {
changeDir(dir)
if err := os.Remove(file); err != nil {
ColorLog("[WARN] Could not remove temporary file: %s\n", err)
logger.Warnf("Could not remove temporary file: %s", err)
}
}
@ -358,8 +345,7 @@ func removeTempFile(dir, file string) {
func formatShellErrOutput(o string) {
for _, line := range strings.Split(o, "\n") {
if line != "" {
ColorLog("[ERRO] -| ")
fmt.Println(line)
logger.Errorf("|> %s", line)
}
}
}
@ -368,13 +354,13 @@ func formatShellErrOutput(o string) {
func formatShellOutput(o string) {
for _, line := range strings.Split(o, "\n") {
if line != "" {
ColorLog("[INFO] -| ")
fmt.Println(line)
logger.Infof("|> %s", line)
}
}
}
const (
// MigrationMainTPL migration main template
MigrationMainTPL = `package main
import(
@ -414,6 +400,7 @@ func main(){
}
`
// MYSQLMigrationDDL MySQL migration SQL
MYSQLMigrationDDL = `
CREATE TABLE migrations (
id_migration int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'surrogate key',
@ -425,7 +412,7 @@ CREATE TABLE migrations (
PRIMARY KEY (id_migration)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
`
// POSTGRESMigrationDDL Postgres migration SQL
POSTGRESMigrationDDL = `
CREATE TYPE migrations_status AS ENUM('update', 'rollback');