546 lines
16 KiB
Go
546 lines
16 KiB
Go
|
package ulog
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"log/syslog"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"reflect"
|
||
|
"regexp"
|
||
|
"runtime"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
"syscall"
|
||
|
"time"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
TIME_NONE int = iota
|
||
|
TIME_DATETIME
|
||
|
TIME_MSDATETIME
|
||
|
TIME_TIMESTAMP
|
||
|
TIME_MSTIMESTAMP
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
cores int
|
||
|
facilities = map[string]syslog.Priority{
|
||
|
"user": syslog.LOG_USER,
|
||
|
"daemon": syslog.LOG_DAEMON,
|
||
|
"local0": syslog.LOG_LOCAL0,
|
||
|
"local1": syslog.LOG_LOCAL1,
|
||
|
"local2": syslog.LOG_LOCAL2,
|
||
|
"local3": syslog.LOG_LOCAL3,
|
||
|
"local4": syslog.LOG_LOCAL4,
|
||
|
"local5": syslog.LOG_LOCAL5,
|
||
|
"local6": syslog.LOG_LOCAL6,
|
||
|
"local7": syslog.LOG_LOCAL7,
|
||
|
}
|
||
|
severities = map[string]syslog.Priority{
|
||
|
"error": syslog.LOG_ERR,
|
||
|
"warning": syslog.LOG_WARNING,
|
||
|
"info": syslog.LOG_INFO,
|
||
|
"debug": syslog.LOG_DEBUG,
|
||
|
}
|
||
|
severityLabels = map[syslog.Priority]string{
|
||
|
syslog.LOG_ERR: "ERRO ",
|
||
|
syslog.LOG_WARNING: "WARN ",
|
||
|
syslog.LOG_INFO: "INFO ",
|
||
|
syslog.LOG_DEBUG: "DBUG ",
|
||
|
}
|
||
|
severityColors = map[syslog.Priority]string{
|
||
|
syslog.LOG_ERR: "\x1b[31m",
|
||
|
syslog.LOG_WARNING: "\x1b[33m",
|
||
|
syslog.LOG_INFO: "\x1b[36m",
|
||
|
syslog.LOG_DEBUG: "\x1b[32m",
|
||
|
}
|
||
|
)
|
||
|
|
||
|
type FileOutput struct {
|
||
|
handle *os.File
|
||
|
last time.Time
|
||
|
}
|
||
|
type ULog struct {
|
||
|
file, console, syslog bool
|
||
|
fileOutputs map[string]*FileOutput
|
||
|
filePath string
|
||
|
fileTime int
|
||
|
fileLast time.Time
|
||
|
fileSeverity bool
|
||
|
consoleHandle io.Writer
|
||
|
consoleTime int
|
||
|
consoleSeverity bool
|
||
|
consoleColors bool
|
||
|
syslogHandle *syslog.Writer
|
||
|
syslogRemote string
|
||
|
syslogName string
|
||
|
syslogFacility syslog.Priority
|
||
|
optionUTC bool
|
||
|
level syslog.Priority
|
||
|
sync.Mutex
|
||
|
}
|
||
|
|
||
|
func New(target string) *ULog {
|
||
|
if cores == 0 {
|
||
|
cores = runtime.NumCPU()
|
||
|
}
|
||
|
log := &ULog{
|
||
|
fileOutputs: map[string]*FileOutput{},
|
||
|
syslogHandle: nil,
|
||
|
}
|
||
|
return log.Load(target)
|
||
|
}
|
||
|
|
||
|
func (this *ULog) Load(target string) *ULog {
|
||
|
this.Close()
|
||
|
if cores > 1 {
|
||
|
this.Lock()
|
||
|
defer this.Unlock()
|
||
|
}
|
||
|
|
||
|
this.file = false
|
||
|
this.filePath = ""
|
||
|
this.fileTime = TIME_DATETIME
|
||
|
this.fileSeverity = true
|
||
|
this.console = false
|
||
|
this.consoleTime = TIME_DATETIME
|
||
|
this.consoleSeverity = true
|
||
|
this.consoleColors = true
|
||
|
this.consoleHandle = os.Stderr
|
||
|
this.syslog = false
|
||
|
this.syslogRemote = ""
|
||
|
this.syslogName = filepath.Base(os.Args[0])
|
||
|
this.syslogFacility = syslog.LOG_DAEMON
|
||
|
this.optionUTC = false
|
||
|
this.level = syslog.LOG_INFO
|
||
|
for _, target := range regexp.MustCompile("(file|console|syslog|option)\\s*\\(([^\\)]*)\\)").FindAllStringSubmatch(target, -1) {
|
||
|
switch strings.ToLower(target[1]) {
|
||
|
case "file":
|
||
|
this.file = true
|
||
|
for _, option := range regexp.MustCompile("([^:=,\\s]+)\\s*[:=]\\s*([^,\\s]+)").FindAllStringSubmatch(target[2], -1) {
|
||
|
switch strings.ToLower(option[1]) {
|
||
|
case "path":
|
||
|
this.filePath = option[2]
|
||
|
case "time":
|
||
|
option[2] = strings.ToLower(option[2])
|
||
|
switch {
|
||
|
case option[2] == "datetime":
|
||
|
this.fileTime = TIME_DATETIME
|
||
|
case option[2] == "msdatetime":
|
||
|
this.fileTime = TIME_MSDATETIME
|
||
|
case option[2] == "stamp" || option[2] == "timestamp":
|
||
|
this.fileTime = TIME_TIMESTAMP
|
||
|
case option[2] == "msstamp" || option[2] == "mstimestamp":
|
||
|
this.fileTime = TIME_MSTIMESTAMP
|
||
|
case option[2] != "1" && option[2] != "true" && option[2] != "on" && option[2] != "yes":
|
||
|
this.fileTime = TIME_NONE
|
||
|
}
|
||
|
case "severity":
|
||
|
option[2] = strings.ToLower(option[2])
|
||
|
if option[2] != "1" && option[2] != "true" && option[2] != "on" && option[2] != "yes" {
|
||
|
this.fileSeverity = false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if this.filePath == "" {
|
||
|
this.file = false
|
||
|
}
|
||
|
case "console":
|
||
|
this.console = true
|
||
|
for _, option := range regexp.MustCompile("([^:=,\\s]+)\\s*[:=]\\s*([^,\\s]+)").FindAllStringSubmatch(target[2], -1) {
|
||
|
option[2] = strings.ToLower(option[2])
|
||
|
switch strings.ToLower(option[1]) {
|
||
|
case "output":
|
||
|
if option[2] == "stdout" {
|
||
|
this.consoleHandle = os.Stdout
|
||
|
}
|
||
|
case "time":
|
||
|
switch {
|
||
|
case option[2] == "datetime":
|
||
|
this.consoleTime = TIME_DATETIME
|
||
|
case option[2] == "msdatetime":
|
||
|
this.consoleTime = TIME_MSDATETIME
|
||
|
case option[2] == "stamp" || option[2] == "timestamp":
|
||
|
this.consoleTime = TIME_TIMESTAMP
|
||
|
case option[2] == "msstamp" || option[2] == "mstimestamp":
|
||
|
this.consoleTime = TIME_MSTIMESTAMP
|
||
|
case option[2] != "1" && option[2] != "true" && option[2] != "on" && option[2] != "yes":
|
||
|
this.consoleTime = TIME_NONE
|
||
|
}
|
||
|
case "severity":
|
||
|
if option[2] != "1" && option[2] != "true" && option[2] != "on" && option[2] != "yes" {
|
||
|
this.consoleSeverity = false
|
||
|
}
|
||
|
case "colors":
|
||
|
if option[2] != "1" && option[2] != "true" && option[2] != "on" && option[2] != "yes" {
|
||
|
this.consoleColors = false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
case "syslog":
|
||
|
this.syslog = true
|
||
|
for _, option := range regexp.MustCompile("([^:=,\\s]+)\\s*[:=]\\s*([^,\\s]+)").FindAllStringSubmatch(target[2], -1) {
|
||
|
switch strings.ToLower(option[1]) {
|
||
|
case "remote":
|
||
|
this.syslogRemote = option[2]
|
||
|
if !regexp.MustCompile(":\\d+$").MatchString(this.syslogRemote) {
|
||
|
this.syslogRemote += ":514"
|
||
|
}
|
||
|
case "name":
|
||
|
this.syslogName = option[2]
|
||
|
case "facility":
|
||
|
this.syslogFacility = facilities[strings.ToLower(option[2])]
|
||
|
}
|
||
|
}
|
||
|
case "option":
|
||
|
for _, option := range regexp.MustCompile("([^:=,\\s]+)\\s*[:=]\\s*([^,\\s]+)").FindAllStringSubmatch(target[2], -1) {
|
||
|
option[2] = strings.ToLower(option[2])
|
||
|
switch strings.ToLower(option[1]) {
|
||
|
case "utc":
|
||
|
if option[2] == "1" || option[2] == "true" || option[2] == "on" || option[2] == "yes" {
|
||
|
this.optionUTC = true
|
||
|
}
|
||
|
case "level":
|
||
|
this.level = severities[strings.ToLower(option[2])]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var info syscall.Termios
|
||
|
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, this.consoleHandle.(*os.File).Fd(), syscall.TCGETS, uintptr(unsafe.Pointer(&info)), 0, 0, 0); err != 0 {
|
||
|
this.consoleColors = false
|
||
|
}
|
||
|
return this
|
||
|
}
|
||
|
|
||
|
func (this *ULog) Close() {
|
||
|
if cores > 1 {
|
||
|
this.Lock()
|
||
|
defer this.Unlock()
|
||
|
}
|
||
|
if this.syslogHandle != nil {
|
||
|
this.syslogHandle.Close()
|
||
|
this.syslogHandle = nil
|
||
|
}
|
||
|
for path, output := range this.fileOutputs {
|
||
|
if output.handle != nil {
|
||
|
output.handle.Close()
|
||
|
}
|
||
|
delete(this.fileOutputs, path)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (this *ULog) SetLevel(level string) {
|
||
|
level = strings.ToLower(level)
|
||
|
switch level {
|
||
|
case "error":
|
||
|
this.level = syslog.LOG_ERR
|
||
|
case "warning":
|
||
|
this.level = syslog.LOG_WARNING
|
||
|
case "info":
|
||
|
this.level = syslog.LOG_INFO
|
||
|
case "debug":
|
||
|
this.level = syslog.LOG_DEBUG
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func strftime(layout string, base time.Time) string {
|
||
|
var output []string
|
||
|
|
||
|
length := len(layout)
|
||
|
for index := 0; index < length; index++ {
|
||
|
switch layout[index] {
|
||
|
case '%':
|
||
|
if index < length-1 {
|
||
|
switch layout[index+1] {
|
||
|
case 'a':
|
||
|
output = append(output, base.Format("Mon"))
|
||
|
case 'A':
|
||
|
output = append(output, base.Format("Monday"))
|
||
|
case 'b':
|
||
|
output = append(output, base.Format("Jan"))
|
||
|
case 'B':
|
||
|
output = append(output, base.Format("January"))
|
||
|
case 'c':
|
||
|
output = append(output, base.Format("Mon Jan 2 15:04:05 2006"))
|
||
|
case 'C':
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Year()/100))
|
||
|
case 'd':
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Day()))
|
||
|
case 'D':
|
||
|
output = append(output, fmt.Sprintf("%02d/%02d/%02d", base.Month(), base.Day(), base.Year()%100))
|
||
|
case 'e':
|
||
|
output = append(output, fmt.Sprintf("%2d", base.Day()))
|
||
|
case 'f':
|
||
|
output = append(output, fmt.Sprintf("%06d", base.Nanosecond()/1000))
|
||
|
case 'F':
|
||
|
output = append(output, fmt.Sprintf("%04d-%02d-%02d", base.Year(), base.Month(), base.Day()))
|
||
|
case 'g':
|
||
|
year, _ := base.ISOWeek()
|
||
|
output = append(output, fmt.Sprintf("%02d", year%100))
|
||
|
case 'G':
|
||
|
year, _ := base.ISOWeek()
|
||
|
output = append(output, fmt.Sprintf("%04d", year))
|
||
|
case 'h':
|
||
|
output = append(output, base.Format("Jan"))
|
||
|
case 'H':
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Hour()))
|
||
|
case 'I':
|
||
|
if base.Hour() == 0 || base.Hour() == 12 {
|
||
|
output = append(output, "12")
|
||
|
} else {
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Hour()%12))
|
||
|
}
|
||
|
case 'j':
|
||
|
output = append(output, fmt.Sprintf("%03d", base.YearDay()))
|
||
|
case 'k':
|
||
|
output = append(output, fmt.Sprintf("%2d", base.Hour()))
|
||
|
case 'l':
|
||
|
if base.Hour() == 0 || base.Hour() == 12 {
|
||
|
output = append(output, "12")
|
||
|
} else {
|
||
|
output = append(output, fmt.Sprintf("%2d", base.Hour()%12))
|
||
|
}
|
||
|
case 'm':
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Month()))
|
||
|
case 'M':
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Minute()))
|
||
|
case 'n':
|
||
|
output = append(output, "\n")
|
||
|
case 'p':
|
||
|
if base.Hour() < 12 {
|
||
|
output = append(output, "AM")
|
||
|
} else {
|
||
|
output = append(output, "PM")
|
||
|
}
|
||
|
case 'P':
|
||
|
if base.Hour() < 12 {
|
||
|
output = append(output, "am")
|
||
|
} else {
|
||
|
output = append(output, "pm")
|
||
|
}
|
||
|
case 'r':
|
||
|
if base.Hour() == 0 || base.Hour() == 12 {
|
||
|
output = append(output, "12")
|
||
|
} else {
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Hour()%12))
|
||
|
}
|
||
|
output = append(output, fmt.Sprintf(":%02d:%02d", base.Minute(), base.Second()))
|
||
|
if base.Hour() < 12 {
|
||
|
output = append(output, " AM")
|
||
|
} else {
|
||
|
output = append(output, " PM")
|
||
|
}
|
||
|
case 'R':
|
||
|
output = append(output, fmt.Sprintf("%02d:%02d", base.Hour(), base.Minute()))
|
||
|
case 's':
|
||
|
output = append(output, fmt.Sprintf("%d", base.Unix()))
|
||
|
case 'S':
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Second()))
|
||
|
case 't':
|
||
|
output = append(output, "\t")
|
||
|
case 'T':
|
||
|
output = append(output, fmt.Sprintf("%02d:%02d:%02d", base.Hour(), base.Minute(), base.Second()))
|
||
|
case 'u':
|
||
|
day := base.Weekday()
|
||
|
if day == 0 {
|
||
|
day = 7
|
||
|
}
|
||
|
output = append(output, fmt.Sprintf("%d", day))
|
||
|
case 'U':
|
||
|
output = append(output, fmt.Sprintf("%d", (base.YearDay()+6-int(base.Weekday()))/7))
|
||
|
case 'V':
|
||
|
_, week := base.ISOWeek()
|
||
|
output = append(output, fmt.Sprintf("%02d", week))
|
||
|
case 'w':
|
||
|
output = append(output, fmt.Sprintf("%d", base.Weekday()))
|
||
|
case 'W':
|
||
|
day := int(base.Weekday())
|
||
|
if day == 0 {
|
||
|
day = 6
|
||
|
} else {
|
||
|
day -= 1
|
||
|
}
|
||
|
output = append(output, fmt.Sprintf("%d", (base.YearDay()+6-day)/7))
|
||
|
case 'x':
|
||
|
output = append(output, fmt.Sprintf("%02d/%02d/%02d", base.Month(), base.Day(), base.Year()%100))
|
||
|
case 'X':
|
||
|
output = append(output, fmt.Sprintf("%02d:%02d:%02d", base.Hour(), base.Minute(), base.Second()))
|
||
|
case 'y':
|
||
|
output = append(output, fmt.Sprintf("%02d", base.Year()%100))
|
||
|
case 'Y':
|
||
|
output = append(output, fmt.Sprintf("%04d", base.Year()))
|
||
|
case 'z':
|
||
|
output = append(output, base.Format("-0700"))
|
||
|
case 'Z':
|
||
|
output = append(output, base.Format("MST"))
|
||
|
case '%':
|
||
|
output = append(output, "%")
|
||
|
}
|
||
|
index++
|
||
|
}
|
||
|
default:
|
||
|
output = append(output, string(layout[index]))
|
||
|
}
|
||
|
}
|
||
|
return strings.Join(output, "")
|
||
|
}
|
||
|
|
||
|
func (this *ULog) log(now time.Time, severity syslog.Priority, xlayout interface{}, a ...interface{}) {
|
||
|
var err error
|
||
|
if this.level < severity || (!this.syslog && !this.file && !this.console) {
|
||
|
return
|
||
|
}
|
||
|
layout := ""
|
||
|
switch reflect.TypeOf(xlayout).Kind() {
|
||
|
case reflect.Map:
|
||
|
var buffer bytes.Buffer
|
||
|
|
||
|
encoder := json.NewEncoder(&buffer)
|
||
|
encoder.SetEscapeHTML(false)
|
||
|
if err := encoder.Encode(xlayout); err == nil {
|
||
|
layout = "%s"
|
||
|
a = []interface{}{bytes.TrimSpace(buffer.Bytes())}
|
||
|
}
|
||
|
case reflect.String:
|
||
|
layout = xlayout.(string)
|
||
|
}
|
||
|
layout = strings.TrimSpace(layout)
|
||
|
if this.syslog {
|
||
|
if this.syslogHandle == nil {
|
||
|
if cores > 1 {
|
||
|
this.Lock()
|
||
|
}
|
||
|
if this.syslogHandle == nil {
|
||
|
protocol := ""
|
||
|
if this.syslogRemote != "" {
|
||
|
protocol = "udp"
|
||
|
}
|
||
|
if this.syslogHandle, err = syslog.Dial(protocol, this.syslogRemote, this.syslogFacility, this.syslogName); err != nil {
|
||
|
this.syslogHandle = nil
|
||
|
}
|
||
|
}
|
||
|
if cores > 1 {
|
||
|
this.Unlock()
|
||
|
}
|
||
|
}
|
||
|
if this.syslogHandle != nil {
|
||
|
switch severity {
|
||
|
case syslog.LOG_ERR:
|
||
|
this.syslogHandle.Err(fmt.Sprintf(layout, a...))
|
||
|
case syslog.LOG_WARNING:
|
||
|
this.syslogHandle.Warning(fmt.Sprintf(layout, a...))
|
||
|
case syslog.LOG_INFO:
|
||
|
this.syslogHandle.Info(fmt.Sprintf(layout, a...))
|
||
|
case syslog.LOG_DEBUG:
|
||
|
this.syslogHandle.Debug(fmt.Sprintf(layout, a...))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if this.optionUTC {
|
||
|
now = now.UTC()
|
||
|
} else {
|
||
|
now = now.Local()
|
||
|
}
|
||
|
if this.file {
|
||
|
path := strftime(this.filePath, now)
|
||
|
if cores > 1 {
|
||
|
this.Lock()
|
||
|
}
|
||
|
if this.fileOutputs[path] == nil {
|
||
|
os.MkdirAll(filepath.Dir(path), 0755)
|
||
|
if handle, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644); err == nil {
|
||
|
this.fileOutputs[path] = &FileOutput{handle: handle}
|
||
|
}
|
||
|
}
|
||
|
if this.fileOutputs[path] != nil && this.fileOutputs[path].handle != nil {
|
||
|
prefix := ""
|
||
|
switch this.fileTime {
|
||
|
case TIME_DATETIME:
|
||
|
prefix = fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d ", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
|
||
|
case TIME_MSDATETIME:
|
||
|
prefix = fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d.%03d ", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond()/int(time.Millisecond))
|
||
|
case TIME_TIMESTAMP:
|
||
|
prefix = fmt.Sprintf("%d ", now.Unix())
|
||
|
case TIME_MSTIMESTAMP:
|
||
|
prefix = fmt.Sprintf("%d ", now.UnixNano()/int64(time.Millisecond))
|
||
|
}
|
||
|
if this.fileSeverity {
|
||
|
prefix += severityLabels[severity]
|
||
|
}
|
||
|
this.fileOutputs[path].handle.WriteString(fmt.Sprintf(prefix+layout+"\n", a...))
|
||
|
this.fileOutputs[path].last = now
|
||
|
}
|
||
|
if now.Sub(this.fileLast) >= 5*time.Second {
|
||
|
this.fileLast = now
|
||
|
for path, output := range this.fileOutputs {
|
||
|
if now.Sub(output.last) >= 5*time.Second {
|
||
|
output.handle.Close()
|
||
|
delete(this.fileOutputs, path)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if cores > 1 {
|
||
|
this.Unlock()
|
||
|
}
|
||
|
}
|
||
|
if this.console {
|
||
|
prefix := ""
|
||
|
switch this.consoleTime {
|
||
|
case TIME_DATETIME:
|
||
|
prefix = fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d ", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
|
||
|
case TIME_MSDATETIME:
|
||
|
prefix = fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d.%03d ", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond()/int(time.Millisecond))
|
||
|
case TIME_TIMESTAMP:
|
||
|
prefix = fmt.Sprintf("%d ", now.Unix())
|
||
|
case TIME_MSTIMESTAMP:
|
||
|
prefix = fmt.Sprintf("%d ", now.UnixNano()/int64(time.Millisecond))
|
||
|
}
|
||
|
if this.consoleSeverity {
|
||
|
if this.consoleColors {
|
||
|
prefix += fmt.Sprintf("%s%s\x1b[0m", severityColors[severity], severityLabels[severity])
|
||
|
} else {
|
||
|
prefix += severityLabels[severity]
|
||
|
}
|
||
|
}
|
||
|
if cores > 1 {
|
||
|
this.Lock()
|
||
|
}
|
||
|
fmt.Fprintf(this.consoleHandle, prefix+layout+"\n", a...)
|
||
|
if cores > 1 {
|
||
|
this.Unlock()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (this *ULog) Error(layout interface{}, a ...interface{}) {
|
||
|
this.log(time.Now(), syslog.LOG_ERR, layout, a...)
|
||
|
}
|
||
|
func (this *ULog) Warn(layout interface{}, a ...interface{}) {
|
||
|
this.log(time.Now(), syslog.LOG_WARNING, layout, a...)
|
||
|
}
|
||
|
func (this *ULog) Info(layout interface{}, a ...interface{}) {
|
||
|
this.log(time.Now(), syslog.LOG_INFO, layout, a...)
|
||
|
}
|
||
|
func (this *ULog) Debug(layout interface{}, a ...interface{}) {
|
||
|
this.log(time.Now(), syslog.LOG_DEBUG, layout, a...)
|
||
|
}
|
||
|
|
||
|
func (this *ULog) ErrorTime(now time.Time, layout interface{}, a ...interface{}) {
|
||
|
this.log(now, syslog.LOG_ERR, layout, a...)
|
||
|
}
|
||
|
func (this *ULog) WarnTime(now time.Time, layout interface{}, a ...interface{}) {
|
||
|
this.log(now, syslog.LOG_WARNING, layout, a...)
|
||
|
}
|
||
|
func (this *ULog) InfoTime(now time.Time, layout interface{}, a ...interface{}) {
|
||
|
this.log(now, syslog.LOG_INFO, layout, a...)
|
||
|
}
|
||
|
func (this *ULog) DebugTime(now time.Time, layout interface{}, a ...interface{}) {
|
||
|
this.log(now, syslog.LOG_DEBUG, layout, a...)
|
||
|
}
|