Version 2.0.0

pull/1/head
兔子 5 years ago
parent 22162048be
commit b278688830

@ -0,0 +1,603 @@
package starlog
import (
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
)
var (
// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. This is a global option and affects all colors. For more control
// over each color block use the methods DisableColor() individually.
NoColor = os.Getenv("TERM") == "dumb" ||
(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
// Output defines the standard output of the print functions. By default
// os.Stdout is used.
Output = colorable.NewColorableStdout()
// Error defines a color supporting writer for os.Stderr.
Errors = colorable.NewColorableStderr()
// colorsCache is used to reduce the count of created Color objects and
// allows to reuse already created objects with required Attr.
colorsCache = make(map[Attr]*Color)
colorsCacheMu sync.Mutex // protects colorsCache
)
// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
params []Attr
noColor *bool
}
// Attr defines a single SGR Code
type Attr int
const escape = "\x1b"
// Base attributes
const (
Reset Attr = iota
Bold
Faint
Italic
Underline
BlinkSlow
BlinkRapid
ReverseVideo
Concealed
CrossedOut
)
// Foreground text colors
const (
FgBlack Attr = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta
FgCyan
FgWhite
)
// Foreground Hi-Intensity text colors
const (
FgHiBlack Attr = iota + 90
FgHiRed
FgHiGreen
FgHiYellow
FgHiBlue
FgHiMagenta
FgHiCyan
FgHiWhite
)
// Background text colors
const (
BgBlack Attr = iota + 40
BgRed
BgGreen
BgYellow
BgBlue
BgMagenta
BgCyan
BgWhite
)
// Background Hi-Intensity text colors
const (
BgHiBlack Attr = iota + 100
BgHiRed
BgHiGreen
BgHiYellow
BgHiBlue
BgHiMagenta
BgHiCyan
BgHiWhite
)
// New returns a newly created color object.
func NewColor(value ...Attr) *Color {
c := &Color{params: make([]Attr, 0)}
c.Add(value...)
return c
}
// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...Attr) *Color {
c := NewColor(p...)
c.Set()
return c
}
// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
if NoColor {
return
}
fmt.Fprintf(Output, "%s[%dm", escape, Reset)
}
// Set sets the SGR sequence.
func (c *Color) Set() *Color {
if c.isNoColorSet() {
return c
}
fmt.Fprintf(Output, c.format())
return c
}
func (c *Color) unset() {
if c.isNoColorSet() {
return
}
Unset()
}
func (c *Color) setWriter(w io.Writer) *Color {
if c.isNoColorSet() {
return c
}
fmt.Fprintf(w, c.format())
return c
}
func (c *Color) unsetWriter(w io.Writer) {
if c.isNoColorSet() {
return
}
if NoColor {
return
}
fmt.Fprintf(w, "%s[%dm", escape, Reset)
}
// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attr) *Color {
c.params = append(c.params, value...)
return c
}
func (c *Color) prepend(value Attr) {
c.params = append(c.params, 0)
copy(c.params[1:], c.params[0:])
c.params[0] = value
}
// Fprint formats using the default formats for its operands and writes to w.
// Spaces are added between operands when neither is a string.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
c.setWriter(w)
defer c.unsetWriter(w)
return fmt.Fprint(w, a...)
}
// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
// string. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Print(a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprint(Output, a...)
}
// Fprintf formats according to a format specifier and writes to w.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
c.setWriter(w)
defer c.unsetWriter(w)
return fmt.Fprintf(w, format, a...)
}
// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprintf(Output, format, a...)
}
// Fprintln formats using the default formats for its operands and writes to w.
// Spaces are always added between operands and a newline is appended.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
c.setWriter(w)
defer c.unsetWriter(w)
return fmt.Fprintln(w, a...)
}
// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Println(a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprintln(Output, a...)
}
// Sprint is just like Print, but returns a string instead of printing it.
func (c *Color) Sprint(a ...interface{}) string {
return c.wrap(fmt.Sprint(a...))
}
// Sprintln is just like Println, but returns a string instead of printing it.
func (c *Color) Sprintln(a ...interface{}) string {
return c.wrap(fmt.Sprintln(a...))
}
// Sprintf is just like Printf, but returns a string instead of printing it.
func (c *Color) Sprintf(format string, a ...interface{}) string {
return c.wrap(fmt.Sprintf(format, a...))
}
// FprintFunc returns a new function that prints the passed arguments as
// colorized with color.Fprint().
func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
return func(w io.Writer, a ...interface{}) {
c.Fprint(w, a...)
}
}
// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
return func(a ...interface{}) {
c.Print(a...)
}
}
// FprintfFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintf().
func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
return func(w io.Writer, format string, a ...interface{}) {
c.Fprintf(w, format, a...)
}
}
// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
return func(format string, a ...interface{}) {
c.Printf(format, a...)
}
}
// FprintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintln().
func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
return func(w io.Writer, a ...interface{}) {
c.Fprintln(w, a...)
}
}
// PrintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Println().
func (c *Color) PrintlnFunc() func(a ...interface{}) {
return func(a ...interface{}) {
c.Println(a...)
}
}
// SprintFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprint(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output, example:
//
// put := New(FgYellow).SprintFunc()
// fmt.Fprintf(color.Output, "This is a %s", put("warning"))
func (c *Color) SprintFunc() func(a ...interface{}) string {
return func(a ...interface{}) string {
return c.wrap(fmt.Sprint(a...))
}
}
// SprintfFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
return func(format string, a ...interface{}) string {
return c.wrap(fmt.Sprintf(format, a...))
}
}
// SprintlnFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
return func(a ...interface{}) string {
return c.wrap(fmt.Sprintln(a...))
}
}
// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m"
// an example output might be: "1;36" -> bold cyan
func (c *Color) sequence() string {
format := make([]string, len(c.params))
for i, v := range c.params {
format[i] = strconv.Itoa(int(v))
}
return strings.Join(format, ";")
}
// wrap wraps the s string with the colors attributes. The string is ready to
// be printed.
func (c *Color) wrap(s string) string {
if c.isNoColorSet() {
return s
}
return c.format() + s + c.unformat()
}
func (c *Color) format() string {
return fmt.Sprintf("%s[%sm", escape, c.sequence())
}
func (c *Color) unformat() string {
return fmt.Sprintf("%s[%dm", escape, Reset)
}
// DisableColor disables the color output. Useful to not change any existing
// code and still being able to output. Can be used for flags like
// "--no-color". To enable back use EnableColor() method.
func (c *Color) DisableColor() {
c.noColor = boolPtr(true)
}
// EnableColor enables the color output. Use it in conjunction with
// DisableColor(). Otherwise this method has no side effects.
func (c *Color) EnableColor() {
c.noColor = boolPtr(false)
}
func (c *Color) isNoColorSet() bool {
// check first if we have user setted action
if c.noColor != nil {
return *c.noColor
}
// if not return the global option, which is disabled by default
return NoColor
}
// Equals returns a boolean value indicating whether two colors are equal.
func (c *Color) Equals(c2 *Color) bool {
if len(c.params) != len(c2.params) {
return false
}
for _, attr := range c.params {
if !c2.attrExists(attr) {
return false
}
}
return true
}
func (c *Color) attrExists(a Attr) bool {
for _, attr := range c.params {
if attr == a {
return true
}
}
return false
}
func boolPtr(v bool) *bool {
return &v
}
func getCachedColor(p Attr) *Color {
colorsCacheMu.Lock()
defer colorsCacheMu.Unlock()
c, ok := colorsCache[p]
if !ok {
c = NewColor(p)
colorsCache[p] = c
}
return c
}
func colorPrint(format string, p Attr, a ...interface{}) {
c := getCachedColor(p)
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
if len(a) == 0 {
c.Print(format)
} else {
c.Printf(format, a...)
}
}
func colorString(format string, p Attr, a ...interface{}) string {
c := getCachedColor(p)
if len(a) == 0 {
return c.SprintFunc()(format)
}
return c.SprintfFunc()(format, a...)
}
// Black is a convenient helper function to print with black foreground. A
// newline is appended to format by default.
func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }
// Red is a convenient helper function to print with red foreground. A
// newline is appended to format by default.
func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }
// Green is a convenient helper function to print with green foreground. A
// newline is appended to format by default.
func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }
// Yellow is a convenient helper function to print with yellow foreground.
// A newline is appended to format by default.
func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }
// Blue is a convenient helper function to print with blue foreground. A
// newline is appended to format by default.
func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }
// Magenta is a convenient helper function to print with magenta foreground.
// A newline is appended to format by default.
func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }
// Cyan is a convenient helper function to print with cyan foreground. A
// newline is appended to format by default.
func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }
// White is a convenient helper function to print with white foreground. A
// newline is appended to format by default.
func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }
// BlackString is a convenient helper function to return a string with black
// foreground.
func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }
// RedString is a convenient helper function to return a string with red
// foreground.
func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }
// GreenString is a convenient helper function to return a string with green
// foreground.
func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }
// YellowString is a convenient helper function to return a string with yellow
// foreground.
func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }
// BlueString is a convenient helper function to return a string with blue
// foreground.
func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }
// MagentaString is a convenient helper function to return a string with magenta
// foreground.
func MagentaString(format string, a ...interface{}) string {
return colorString(format, FgMagenta, a...)
}
// CyanString is a convenient helper function to return a string with cyan
// foreground.
func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }
// WhiteString is a convenient helper function to return a string with white
// foreground.
func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }
// HiBlack is a convenient helper function to print with hi-intensity black foreground. A
// newline is appended to format by default.
func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) }
// HiRed is a convenient helper function to print with hi-intensity red foreground. A
// newline is appended to format by default.
func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) }
// HiGreen is a convenient helper function to print with hi-intensity green foreground. A
// newline is appended to format by default.
func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) }
// HiYellow is a convenient helper function to print with hi-intensity yellow foreground.
// A newline is appended to format by default.
func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) }
// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A
// newline is appended to format by default.
func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) }
// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground.
// A newline is appended to format by default.
func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) }
// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A
// newline is appended to format by default.
func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) }
// HiWhite is a convenient helper function to print with hi-intensity white foreground. A
// newline is appended to format by default.
func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) }
// HiBlackString is a convenient helper function to return a string with hi-intensity black
// foreground.
func HiBlackString(format string, a ...interface{}) string {
return colorString(format, FgHiBlack, a...)
}
// HiRedString is a convenient helper function to return a string with hi-intensity red
// foreground.
func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) }
// HiGreenString is a convenient helper function to return a string with hi-intensity green
// foreground.
func HiGreenString(format string, a ...interface{}) string {
return colorString(format, FgHiGreen, a...)
}
// HiYellowString is a convenient helper function to return a string with hi-intensity yellow
// foreground.
func HiYellowString(format string, a ...interface{}) string {
return colorString(format, FgHiYellow, a...)
}
// HiBlueString is a convenient helper function to return a string with hi-intensity blue
// foreground.
func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) }
// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta
// foreground.
func HiMagentaString(format string, a ...interface{}) string {
return colorString(format, FgHiMagenta, a...)
}
// HiCyanString is a convenient helper function to return a string with hi-intensity cyan
// foreground.
func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) }
// HiWhiteString is a convenient helper function to return a string with hi-intensity white
// foreground.
func HiWhiteString(format string, a ...interface{}) string {
return colorString(format, FgHiWhite, a...)
}

@ -2,6 +2,7 @@ package starlog
import (
"fmt"
"io"
"os"
"path/filepath"
"runtime"
@ -9,25 +10,9 @@ import (
"sync"
"time"
"github.com/fatih/color"
"github.com/mattn/go-colorable"
)
// Base attributes
const (
BLUE = color.FgBlue
BLACK = color.FgBlack
CYAN = color.FgCyan
GREEN = color.FgGreen
MAGENTA = color.FgMagenta
RED = color.FgRed
WHITE = color.FgWhite
YELLOW = color.FgYellow
GREY = color.FgHiRed
BOLD = color.Bold
)
// Log Level
const (
LvDebug = iota
LvInfo
@ -39,7 +24,6 @@ const (
LvFatal
)
// Log Init Data
var (
levels = map[int]string{
LvDebug: "DEBUG",
@ -51,268 +35,455 @@ var (
LvPanic: "PANIC",
LvFatal: "FATAL",
}
Colors = map[int][]color.Attribute{
LvDebug: []color.Attribute{WHITE},
LvInfo: []color.Attribute{GREEN},
LvNotice: []color.Attribute{BLUE},
LvWarning: []color.Attribute{YELLOW},
LvError: []color.Attribute{MAGENTA},
LvCritical: []color.Attribute{RED, BOLD},
LvPanic: []color.Attribute{RED, BOLD},
LvFatal: []color.Attribute{RED},
Colors = map[int][]Attr{
LvDebug: []Attr{FgWhite},
LvInfo: []Attr{FgGreen},
LvNotice: []Attr{FgBlue},
LvWarning: []Attr{FgYellow},
LvError: []Attr{FgMagenta},
LvCritical: []Attr{FgRed, Bold},
LvPanic: []Attr{FgRed, Bold},
LvFatal: []Attr{FgRed},
}
LogLevel int = 0
ShowLine, ShowLevel, DoWrite, DoShow, switching bool = true, true, true, true, false
loghandle *os.File = nil
HandleFunc func([]color.Attribute, string)
lock sync.WaitGroup
waiting = make(chan int, 1)
)
// Output 使用此进行windows支持
var Output = colorable.NewColorableStdout()
func write(logs string) {
var i int
lock.Add(1)
defer lock.Done()
for switching {
type StarLogger struct {
mu sync.Mutex
lock sync.Mutex
out io.Writer
ShowLine bool
ShowLevel bool
DoWrite bool
DoShow bool
switching bool
//HandleFunc
waiting chan int
outshow io.Writer
LogLevel int
HandleFunc func([]Attr, string)
StdFuncColor bool
}
var Std = New(nil)
func init() {
Std.DoShow = true
}
func New(out io.Writer) *StarLogger {
logger := new(StarLogger)
logger.DoShow = false
logger.ShowLevel = true
logger.ShowLine = true
logger.DoWrite = true
logger.out = out
logger.outshow = colorable.NewColorableStdout()
logger.StdFuncColor = true
return logger
}
func (logger *StarLogger) write(logstr string) {
if (!logger.DoWrite) || (logger.out == nil) {
return
}
i := 0
for logger.switching {
time.Sleep(time.Millisecond * 100)
i++
if i > 20 {
return
}
}
if loghandle == nil {
if &(logger.out) == nil {
return
}
loghandle.WriteString(logs)
logger.out.Write([]byte(logstr))
}
func (logger *StarLogger) OutPut(logstr string) {
logger.out.Write([]byte(logstr))
}
func output(level int, showline, showlv, dowrite, doshow bool, strlog string) {
func (logger *StarLogger) output(level int, logstr string) {
var logs string
waiting <- 1
defer func() {
<-waiting
}()
if level < LogLevel {
logger.mu.Lock()
defer logger.mu.Unlock()
if level < logger.LogLevel {
return
}
_, fname, line, _ := runtime.Caller(2)
_, fname, line, _ := runtime.Caller(3)
fname = filepath.Base(fname)
date := time.Now().Format("2006-01-02 15:04:05 Mon")
if showline && showlv {
logs = fmt.Sprintf("%s %s %s %s", date, fname+":"+strconv.Itoa(line), `[`+levels[level]+`]`, strlog)
} else if showline && !showlv {
logs = fmt.Sprintf("%s %s %s", date, fname+":"+strconv.Itoa(line), strlog)
} else if !showline && showlv {
logs = fmt.Sprintf("%s %s %s", date, `[`+levels[level]+`]`, strlog)
date := time.Now().Format("2006-01-02 15:04:05.000 Mon")
if logger.ShowLine && logger.ShowLevel {
logs = fmt.Sprintf("%s %s %s %s", date, fname+":"+strconv.Itoa(line), `[`+levels[level]+`]`, logstr)
} else if logger.ShowLine && !logger.ShowLevel {
logs = fmt.Sprintf("%s %s %s", date, fname+":"+strconv.Itoa(line), logstr)
} else if !logger.ShowLine && logger.ShowLevel {
logs = fmt.Sprintf("%s %s %s", date, `[`+levels[level]+`]`, logstr)
} else {
logs = fmt.Sprintf("%s %s", date, strlog)
logs = fmt.Sprintf("%s %s", date, logstr)
}
if doshow {
logcolor := color.New(Colors[level]...)
logstr := logcolor.Sprint(logs)
fmt.Fprint(Output, logstr)
if logger.DoShow {
logcolor := NewColor(Colors[level]...)
logcolor.Fprint(logger.outshow, logs)
}
if HandleFunc != nil {
go HandleFunc(Colors[level], logs)
if logger.HandleFunc != nil {
go logger.HandleFunc(Colors[level], logs)
}
if dowrite {
write(logs)
if logger.DoWrite {
logger.write(logs)
}
}
// StdPrint 进行stdout标准输出
func StdPrint(c1, c2 color.Attribute, str ...interface{}) {
waiting <- 1
defer func() {
<-waiting
}()
colorstr := color.New(c1, c2)
colorstr.Fprint(Output, str...)
func (logger *StarLogger) Debug(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
logger.output(LvDebug, strs)
}
func StdPrintf(c1, c2 color.Attribute, format string, str ...interface{}) {
waiting <- 1
defer func() {
<-waiting
}()
colorstr := color.New(c1, c2)
colorstr.Fprintf(Output, format, str...)
func Debug(str ...interface{}) {
Std.Debug(str...)
}
func StdPrintln(c1, c2 color.Attribute, str ...interface{}) {
waiting <- 1
defer func() {
<-waiting
}()
colorstr := color.New(c1, c2)
colorstr.Fprintln(Output, str...)
func (logger *StarLogger) Debugf(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
logger.output(LvDebug, strs)
}
func Print(c1, c2 color.Attribute, str ...interface{}) {
StdPrint(c1, c2, str...)
write(fmt.Sprint(str...))
func Debugf(format string, str ...interface{}) {
Std.Debugf(format, str...)
}
func Printf(c1, c2 color.Attribute, format string, str ...interface{}) {
StdPrintf(c1, c2, format, str...)
write(fmt.Sprintf(format, str...))
func (logger *StarLogger) Debugln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
logger.output(LvDebug, strs)
}
func Println(c1, c2 color.Attribute, str ...interface{}) {
StdPrintln(c1, c2, str...)
write(fmt.Sprintln(str...))
func Debugln(str ...interface{}) {
Std.Debugln(str...)
}
func Debug(str ...interface{}) {
func (logger *StarLogger) Info(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
output(LvDebug, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvInfo, strs)
}
func Debugf(format string, str ...interface{}) {
strs := fmt.Sprintf(format, str...)
output(LvDebug, ShowLine, ShowLevel, DoWrite, DoShow, strs)
func Info(str ...interface{}) {
Std.Info(str...)
}
func Debugln(str ...interface{}) {
strs := fmt.Sprintln(str...)
output(LvDebug, ShowLine, ShowLevel, DoWrite, DoShow, strs)
func (logger *StarLogger) Infof(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
logger.output(LvInfo, strs)
}
func Info(str ...interface{}) {
strs := fmt.Sprint(str...)
output(LvInfo, ShowLine, ShowLevel, DoWrite, DoShow, strs)
func Infof(format string, str ...interface{}) {
Std.Infof(format, str...)
}
func Infof(format string, str ...interface{}) {
strs := fmt.Sprintf(format, str...)
output(LvInfo, ShowLine, ShowLevel, DoWrite, DoShow, strs)
func (logger *StarLogger) Infoln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
logger.output(LvInfo, strs)
}
func Infoln(str ...interface{}) {
strs := fmt.Sprintln(str...)
output(LvInfo, ShowLine, ShowLevel, DoWrite, DoShow, strs)
Std.Infoln(str...)
}
func Notice(str ...interface{}) {
func (logger *StarLogger) Notice(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
output(LvNotice, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvNotice, strs)
}
func Noticef(format string, str ...interface{}) {
func Notice(str ...interface{}) {
Std.Notice(str...)
}
func (logger *StarLogger) Noticef(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
output(LvNotice, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvNotice, strs)
}
func Noticeln(str ...interface{}) {
func Noticef(format string, str ...interface{}) {
Std.Noticef(format, str...)
}
func (logger *StarLogger) Noticeln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
output(LvNotice, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvNotice, strs)
}
func Warning(str ...interface{}) {
func Noticeln(str ...interface{}) {
Std.Noticeln(str...)
}
func (logger *StarLogger) Warning(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
output(LvWarning, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvWarning, strs)
}
func Warningf(format string, str ...interface{}) {
func Warning(str ...interface{}) {
Std.Warning(str...)
}
func (logger *StarLogger) Warningf(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
output(LvWarning, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvWarning, strs)
}
func Warningln(str ...interface{}) {
func Warningf(format string, str ...interface{}) {
Std.Warningf(format, str...)
}
func (logger *StarLogger) Warningln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
output(LvWarning, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvWarning, strs)
}
func Error(str ...interface{}) {
func Warningln(str ...interface{}) {
Std.Warningln(str...)
}
func (logger *StarLogger) Error(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
output(LvError, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvError, strs)
}
func Errorf(format string, str ...interface{}) {
func Error(str ...interface{}) {
Std.Error(str...)
}
func (logger *StarLogger) Errorf(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
output(LvError, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvError, strs)
}
func Errorln(str ...interface{}) {
func Errorf(format string, str ...interface{}) {
Std.Errorf(format, str...)
}
func (logger *StarLogger) Errorln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
output(LvError, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvError, strs)
}
func Critical(str ...interface{}) {
func Errorln(str ...interface{}) {
Std.Errorln(str...)
}
func (logger *StarLogger) Critical(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
output(LvCritical, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvCritical, strs)
}
func Criticalf(format string, str ...interface{}) {
func Critical(str ...interface{}) {
Std.Critical(str...)
}
func (logger *StarLogger) Criticalf(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
output(LvCritical, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvCritical, strs)
}
func Criticalln(str ...interface{}) {
func Criticalf(format string, str ...interface{}) {
Std.Criticalf(format, str...)
}
func (logger *StarLogger) Criticalln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
output(LvCritical, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvCritical, strs)
}
func Fatal(str ...interface{}) {
func Criticalln(str ...interface{}) {
Std.Criticalln(str...)
}
func (logger *StarLogger) Fatal(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
output(LvFatal, ShowLine, ShowLevel, DoWrite, DoShow, strs)
CloseLog()
logger.output(LvFatal, strs)
os.Exit(9)
}
func Fatalf(format string, str ...interface{}) {
func Fatal(str ...interface{}) {
Std.Fatal(str...)
}
func (logger *StarLogger) Fatalf(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
output(LvFatal, ShowLine, ShowLevel, DoWrite, DoShow, strs)
CloseLog()
logger.output(LvFatal, strs)
os.Exit(9)
}
func Fatalln(str ...interface{}) {
func Fatalf(format string, str ...interface{}) {
Std.Fatalf(format, str...)
}
func (logger *StarLogger) Fatalln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
output(LvFatal, ShowLine, ShowLevel, DoWrite, DoShow, strs)
CloseLog()
logger.output(LvFatal, strs)
os.Exit(9)
}
func Panic(str ...interface{}) {
func Fatalln(str ...interface{}) {
Std.Fatalln(str...)
}
func (logger *StarLogger) Panic(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
output(LvPanic, ShowLine, ShowLevel, DoWrite, DoShow, strs)
logger.output(LvPanic, strs)
panic(str)
}
func Panicf(format string, str ...interface{}) {
func Panic(str ...interface{}) {
Std.Panic(str...)
}
func (logger *StarLogger) Panicf(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
output(LvPanic, ShowLine, ShowLevel, DoWrite, DoShow, strs)
panic(strs)
logger.output(LvPanic, strs)
panic(fmt.Sprintf(format, str...))
}
func Panicf(format string, str ...interface{}) {
Std.Panicf(format, str...)
}
func (logger *StarLogger) Panicln(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
logger.output(LvPanic, strs)
panic(fmt.Sprintln(str...))
}
func Panicln(str ...interface{}) {
Std.Panicln(str...)
}
func (logger *StarLogger) Print(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprint(str...)
logger.OutPut(strs)
}
func Print(str ...interface{}) {
Std.Print(str...)
}
func (logger *StarLogger) Printf(format string, str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintf(format, str...)
logger.OutPut(strs)
}
func Printf(format string, str ...interface{}) {
Std.Printf(format, str...)
}
func (logger *StarLogger) Println(str ...interface{}) {
logger.lock.Lock()
defer logger.lock.Unlock()
strs := fmt.Sprintln(str...)
output(LvPanic, ShowLine, ShowLevel, DoWrite, DoShow, strs)
panic(str)
logger.OutPut(strs)
}
func Println(str ...interface{}) {
Std.Println(str...)
}
func StdPrint(c []Attr, str ...interface{}) {
Std.lock.Lock()
defer Std.lock.Unlock()
colorstr := NewColor(c...)
colorstr.Print(str...)
if Std.StdFuncColor && Std.HandleFunc != nil {
go Std.HandleFunc(c, fmt.Sprint(str...))
}
}
func StdPrintf(c []Attr, format string, str ...interface{}) {
Std.lock.Lock()
defer Std.lock.Unlock()
colorstr := NewColor(c...)
colorstr.Printf(format, str...)
if Std.StdFuncColor && Std.HandleFunc != nil {
go Std.HandleFunc(c, fmt.Sprintf(format, str...))
}
}
func StdPrintln(c []Attr, str ...interface{}) {
Std.lock.Lock()
defer Std.lock.Unlock()
colorstr := NewColor(c...)
colorstr.Println(str...)
if Std.StdFuncColor && Std.HandleFunc != nil {
go Std.HandleFunc(c, fmt.Sprintln(str...))
}
}
func (logger *StarLogger) SwitchOut(out io.Writer) {
logger.lock.Lock()
defer logger.lock.Unlock()
logger.switching = true
logger.out = out
logger.switching = false
}
func SetLogFile(path string) error {
var err error
loghandle, err = os.Create(path)
switching = false
Std.out, err = os.Create(path)
Std.switching = false
return err
}
func SwitchFile(path string) error {
switching = true
if loghandle != nil {
loghandle.Close()
}
Std.switching = true
return SetLogFile(path)
}
func CloseLog() {
lock.Wait()
if loghandle != nil {
loghandle.Close()
}
}

@ -1,18 +1,9 @@
package starlog
import (
"errors"
"testing"
)
func Test_LOG(t *testing.T) {
SetLogFile("./okk.log")
Debugln("这是一个Debug事项")
Infoln("这是一个通知")
err := errors.New("NBM")
Errorln("你牛逼", err)
LogLevel = 1
Debugln("你看不到我了!")
Panicln("我要下线了")
CloseLog()
}

@ -0,0 +1,9 @@
language: go
go:
- tip
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Yasuhiro Matsumoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,48 @@
# go-colorable
[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable)
[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master)
[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)
Colorable writer for windows.
For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
This package is possible to handle escape sequence for ansi color on windows.
## Too Bad!
![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png)
## So Good!
![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png)
## Usage
```go
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
logrus.SetOutput(colorable.NewColorableStdout())
logrus.Info("succeeded")
logrus.Warn("not correct")
logrus.Error("something error")
logrus.Fatal("panic")
```
You can compile above code on non-windows OSs.
## Installation
```
$ go get github.com/mattn/go-colorable
```
# License
MIT
# Author
Yasuhiro Matsumoto (a.k.a mattn)

@ -0,0 +1,16 @@
package main
import (
"bufio"
"fmt"
"github.com/mattn/go-colorable"
)
func main() {
stdOut := bufio.NewWriter(colorable.NewColorableStdout())
fmt.Fprint(stdOut, "\x1B[3GMove to 3rd Column\n")
fmt.Fprint(stdOut, "\x1B[1;2HMove to 2nd Column on 1st Line\n")
stdOut.Flush()
}

@ -0,0 +1,16 @@
package main
import (
"github.com/mattn/go-colorable"
"github.com/sirupsen/logrus"
)
func main() {
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
logrus.SetOutput(colorable.NewColorableStdout())
logrus.Info("succeeded")
logrus.Warn("not correct")
logrus.Error("something error")
logrus.Fatal("panic")
}

@ -0,0 +1,14 @@
package main
import (
"fmt"
"os"
. "github.com/mattn/go-colorable"
)
func main() {
out := NewColorableStdout()
fmt.Fprint(out, "\x1B]0;TITLE Changed\007(See title and hit any key)")
var c [1]byte
os.Stdin.Read(c[:])
}

@ -0,0 +1,29 @@
// +build appengine
package colorable
import (
"io"
"os"
_ "github.com/mattn/go-isatty"
)
// NewColorable return new instance of Writer which handle escape sequence.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
}
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
func NewColorableStdout() io.Writer {
return os.Stdout
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
func NewColorableStderr() io.Writer {
return os.Stderr
}

@ -0,0 +1,30 @@
// +build !windows
// +build !appengine
package colorable
import (
"io"
"os"
_ "github.com/mattn/go-isatty"
)
// NewColorable return new instance of Writer which handle escape sequence.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
}
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
func NewColorableStdout() io.Writer {
return os.Stdout
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
func NewColorableStderr() io.Writer {
return os.Stderr
}

@ -0,0 +1,83 @@
package colorable
import (
"bytes"
"os"
"runtime"
"testing"
)
// checkEncoding checks that colorable is output encoding agnostic as long as
// the encoding is a superset of ASCII. This implies that one byte not part of
// an ANSI sequence must give exactly one byte in output
func checkEncoding(t *testing.T, data []byte) {
// Send non-UTF8 data to colorable
b := bytes.NewBuffer(make([]byte, 0, 10))
if b.Len() != 0 {
t.FailNow()
}
// TODO move colorable wrapping outside the test
c := NewNonColorable(b)
c.Write(data)
if b.Len()