1
0
mirror of https://github.com/taigrr/godns synced 2025-01-18 04:03:25 -08:00

Add logger back, do more optimization

This commit is contained in:
Timothy 2016-05-26 23:54:20 +08:00
parent 72706fe0ed
commit 47f4ccd08d
5 changed files with 331 additions and 32 deletions

3
.gitignore vendored
View File

@ -22,6 +22,7 @@ _testmain.go
*.exe *.exe
*.test *.test
config.json config.json
*.log
*.swp *.swp
godns godns
@ -29,4 +30,4 @@ vendor/*
/.idea /.idea
/godns.iml /godns.iml
/godns.ipr /godns.ipr
/godns.iws /godns.iws

View File

@ -13,7 +13,7 @@ import (
"github.com/bitly/go-simplejson" "github.com/bitly/go-simplejson"
) )
func get_currentIP(url string) (string, error) { func getCurrentIP(url string) (string, error) {
response, err := http.Get(url) response, err := http.Get(url)
if err != nil { if err != nil {
@ -27,13 +27,13 @@ func get_currentIP(url string) (string, error) {
return string(body), nil return string(body), nil
} }
func generate_header(content url.Values) url.Values { func generateHeader(content url.Values) url.Values {
header := url.Values{} header := url.Values{}
if(Configuration.LoginToken!=""){ if configuration.LoginToken != "" {
header.Add("login_token", Configuration.LoginToken) header.Add("login_token", configuration.LoginToken)
}else{ } else {
header.Add("login_email", Configuration.Email) header.Add("login_email", configuration.Email)
header.Add("login_password", Configuration.Password) header.Add("login_password", configuration.Password)
} }
header.Add("format", "json") header.Add("format", "json")
header.Add("lang", "en") header.Add("lang", "en")
@ -48,11 +48,11 @@ func generate_header(content url.Values) url.Values {
return header return header
} }
func api_version() { func apiVersion() {
post_data("/Info.Version", nil) postData("/Info.Version", nil)
} }
func get_domain(name string) int64 { func getDomain(name string) int64 {
var ret int64 var ret int64
values := url.Values{} values := url.Values{}
@ -60,17 +60,17 @@ func get_domain(name string) int64 {
values.Add("offset", "0") values.Add("offset", "0")
values.Add("length", "20") values.Add("length", "20")
response, err := post_data("/Domain.List", values) response, err := postData("/Domain.List", values)
if err != nil { if err != nil {
log.Println("Failed to get domain list...") log.Println("Failed to get domain list...")
return -1 return -1
} }
sjson, parse_err := simplejson.NewJson([]byte(response)) sjson, parseErr := simplejson.NewJson([]byte(response))
if parse_err != nil { if parseErr != nil {
log.Println(parse_err) log.Println(parseErr)
return -1 return -1
} }
@ -100,16 +100,16 @@ func get_domain(name string) int64 {
return ret return ret
} }
func get_subdomain(domain_id int64, name string) (string, string) { func getSubDomain(domainID int64, name string) (string, string) {
log.Println("debug:", domain_id, name) log.Println("debug:", domainID, name)
var ret, ip string var ret, ip string
value := url.Values{} value := url.Values{}
value.Add("domain_id", strconv.FormatInt(domain_id, 10)) value.Add("domain_id", strconv.FormatInt(domainID, 10))
value.Add("offset", "0") value.Add("offset", "0")
value.Add("length", "1") value.Add("length", "1")
value.Add("sub_domain", name) value.Add("sub_domain", name)
response, err := post_data("/Record.List", value) response, err := postData("/Record.List", value)
if err != nil { if err != nil {
log.Println("Failed to get domain list") log.Println("Failed to get domain list")
@ -144,7 +144,7 @@ func get_subdomain(domain_id int64, name string) (string, string) {
return ret, ip return ret, ip
} }
func update_ip(domain_id int64, sub_domain_id string, sub_domain_name string, ip string) { func updateIP(domain_id int64, sub_domain_id string, sub_domain_name string, ip string) {
value := url.Values{} value := url.Values{}
value.Add("domain_id", strconv.FormatInt(domain_id, 10)) value.Add("domain_id", strconv.FormatInt(domain_id, 10))
value.Add("record_id", sub_domain_id) value.Add("record_id", sub_domain_id)
@ -153,7 +153,7 @@ func update_ip(domain_id int64, sub_domain_id string, sub_domain_name string, ip
value.Add("record_line", "默认") value.Add("record_line", "默认")
value.Add("value", ip) value.Add("value", ip)
response, err := post_data("/Record.Modify", value) response, err := postData("/Record.Modify", value)
if err != nil { if err != nil {
log.Println("Failed to update record to new IP!") log.Println("Failed to update record to new IP!")
@ -174,13 +174,13 @@ func update_ip(domain_id int64, sub_domain_id string, sub_domain_name string, ip
} }
func post_data(url string, content url.Values) (string, error) { func postData(url string, content url.Values) (string, error) {
client := &http.Client{} client := &http.Client{}
values := generate_header(content) values := generateHeader(content)
req, _ := http.NewRequest("POST", "https://dnsapi.cn"+url, strings.NewReader(values.Encode())) req, _ := http.NewRequest("POST", "https://dnsapi.cn"+url, strings.NewReader(values.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("User-Agent", fmt.Sprintf("GoDNS/0.1 (%s)", Configuration.Email)) req.Header.Set("User-Agent", fmt.Sprintf("GoDNS/0.1 (%s)", configuration.Email))
response, err := client.Do(req) response, err := client.Do(req)
defer response.Body.Close() defer response.Body.Close()

View File

@ -4,8 +4,8 @@ import (
"testing" "testing"
) )
func Test_get_current_IP(t *testing.T) { func testGetCurrentIP(t *testing.T) {
ip, _ := get_currentIP("http://members.3322.org/dyndns/getip") ip, _ := getCurrentIP("http://members.3322.org/dyndns/getip")
if ip == "" { if ip == "" {
t.Log("IP is empty...") t.Log("IP is empty...")

View File

@ -16,7 +16,7 @@ const (
) )
var ( var (
Configuration Settings configuration Settings
optConf = flag.String("c", "./config.json", "config file") optConf = flag.String("c", "./config.json", "config file")
optCommand = flag.String("s", "", "send signal to a master process: stop, quit, reopen, reload") optCommand = flag.String("s", "", "send signal to a master process: stop, quit, reopen, reload")
optHelp = flag.Bool("h", false, "this help") optHelp = flag.Bool("h", false, "this help")
@ -35,7 +35,13 @@ func main() {
} }
var err error var err error
Configuration, err = LoadSettings(*optConf) configuration, err = LoadSettings(*optConf)
err = InitLogger(configuration.Log_Path, configuration.Log_Size, configuration.Log_Num)
if err != nil {
log.Println("InitLogger error:", err)
return
}
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
@ -60,20 +66,20 @@ func dns_loop() {
for { for {
domain_id := get_domain(Configuration.Domain) domain_id := getDomain(configuration.Domain)
if domain_id == -1 { if domain_id == -1 {
continue continue
} }
currentIP, err := get_currentIP(Configuration.IP_Url) currentIP, err := getCurrentIP(configuration.IP_Url)
if err != nil { if err != nil {
log.Println("get_currentIP:", err) log.Println("get_currentIP:", err)
continue continue
} }
sub_domain_id, ip := get_subdomain(domain_id, Configuration.Sub_domain) sub_domain_id, ip := getSubDomain(domain_id, configuration.Sub_domain)
if sub_domain_id == "" || ip == "" { if sub_domain_id == "" || ip == "" {
log.Println("sub_domain:", sub_domain_id, ip) log.Println("sub_domain:", sub_domain_id, ip)
@ -85,7 +91,7 @@ func dns_loop() {
//Continue to check the IP of sub-domain //Continue to check the IP of sub-domain
if len(ip) > 0 && !strings.Contains(currentIP, ip) { if len(ip) > 0 && !strings.Contains(currentIP, ip) {
log.Println("Start to update record IP...") log.Println("Start to update record IP...")
update_ip(domain_id, sub_domain_id, Configuration.Sub_domain, currentIP) updateIP(domain_id, sub_domain_id, configuration.Sub_domain, currentIP)
} else { } else {
log.Println("Current IP is same as domain IP, no need to update...") log.Println("Current IP is same as domain IP, no need to update...")
} }

292
logger.go Normal file
View File

@ -0,0 +1,292 @@
package main
import (
"bufio"
"bytes"
"errors"
"io"
"io/ioutil"
"log"
"os"
"runtime/debug"
"strconv"
"strings"
"sync"
"time"
)
const (
L_INFO int = iota
L_WARNING
L_DEBUG
PRE_INFO = "[ INFO]"
PRE_WARNING = "[WARNING]"
PRE_DEBUG = "[ DEBUG]"
)
type Logger struct {
DEV_MODE bool
fd *os.File
size int
num int
level int
mu sync.Mutex
muSplit sync.Mutex
flushInterval int64 //Second
flushSize int
buf *bytes.Buffer
log *log.Logger
}
func NewLogger(logfile string, size, num int, level int, flushInterval int64, flushSize int) (logger *Logger, err error) {
if size < 1 || num < 1 || level < L_INFO || len(logfile) < 1 {
err = errors.New("NewLogWriter:param error.")
return
}
logger = &Logger{size: size * 1024, num: num, level: level, DEV_MODE: false}
logger.fd, err = os.OpenFile(logfile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.ModeAppend|0666)
if err != nil {
logger = nil
return
}
log.SetOutput(logger)
if flushInterval > 0 && flushSize > 0 {
logger.buf = new(bytes.Buffer)
logger.log = log.New(logger.buf, "", log.LstdFlags)
go func(interval int64, logger *Logger) {
defer func() {
if r := recover(); r != nil {
log.Printf("logger Tick, Recovered in %v:\n %s", r, debug.Stack())
}
}()
c := time.Tick(time.Duration(interval) * time.Second)
for _ = range c {
logger.Flush()
}
}(flushInterval, logger)
}
return
}
func InitLogger(logfile string, size, num int) (err error) {
logger, err := NewLogger(logfile, size, num, L_INFO, -1, -1)
if logger != nil {
logger.level = L_INFO - 1
}
return
}
//immplement write
func (this *Logger) Write(p []byte) (n int, err error) {
if this.DEV_MODE {
n, err = os.Stdout.Write(p)
return
}
n, err = this.fd.Write(p)
if err == nil {
fi, e := this.fd.Stat()
if e != nil {
err = e
return
}
if fi.Size() > int64(this.size) {
this.muSplit.Lock()
defer this.muSplit.Unlock()
fname := fi.Name()
strings.HasSuffix(fname, ".log")
fbase := fname[:len(fname)-3]
oldBs := make([]byte, 0, this.size)
newBs := []byte{}
fd, e := os.Open(fname)
if e != nil {
err = e
return
}
rd := bufio.NewReader(fd)
for {
line, e := rd.ReadBytes('\n')
if e == io.EOF {
break
}
if e != nil {
err = e
return
}
if len(oldBs)+len(line) > this.size {
newBs = append(newBs, line...)
} else {
oldBs = append(oldBs, line...)
}
}
fd.Close()
_, err = this.saveLog(1, fbase, oldBs)
if err != nil {
return
}
err = this.fd.Close()
if err != nil {
return
}
err = os.Remove(fname)
if err != nil {
return
}
this.fd, err = os.OpenFile(fname, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.ModeAppend|0666)
if err != nil {
return
}
_, err = this.fd.Write(newBs)
if err != nil {
return
}
}
}
return
}
func (this *Logger) saveLog(index int, fbase string, data []byte) (n int, err error) {
fn := fbase + strconv.Itoa(index) + ".log"
_, err = os.Stat(fn)
if index < this.num && err == nil {
var b []byte
b, err = ioutil.ReadFile(fn)
if err != nil {
return
}
n, err = this.saveLog(index+1, fbase, b)
if err != nil {
return
}
}
fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm|0666)
if err != nil {
return
}
defer fd.Close()
n, err = fd.Write(data)
return
}
//flush buf data to std log
func (this *Logger) Flush() {
if this.buf.Len() > 0 {
this.mu.Lock()
defer this.mu.Unlock()
log.SetFlags(0)
log.Print(this.buf)
log.SetFlags(log.LstdFlags)
this.buf.Reset()
}
}
//clean prefix and check buf size
func (this *Logger) clean() {
this.log.SetPrefix("")
if this.buf.Len()/1024 > this.flushSize {
go this.Flush()
}
}
func (this *Logger) setPrefix(lv int) bool {
if lv > this.level {
return false
}
switch lv {
case L_INFO:
this.log.SetPrefix(PRE_INFO)
case L_WARNING:
this.log.SetPrefix(PRE_WARNING)
case L_DEBUG:
this.log.SetPrefix(PRE_DEBUG)
default:
return false
}
return true
}
func (this *Logger) logPrint(lv int, args ...interface{}) {
this.mu.Lock()
defer this.mu.Unlock()
if !this.setPrefix(lv) {
return
}
this.log.Print(args...)
this.clean()
}
func (this *Logger) logPrintln(lv int, args ...interface{}) {
this.mu.Lock()
defer this.mu.Unlock()
if !this.setPrefix(lv) {
return
}
this.log.Println(args...)
this.clean()
}
func (this *Logger) logPrintf(lv int, format string, args ...interface{}) {
this.mu.Lock()
defer this.mu.Unlock()
if !this.setPrefix(lv) {
return
}
this.log.Printf(format, args...)
this.clean()
}
//close fd
func (this *Logger) Close() {
if this.fd != nil {
this.Flush()
this.fd.Close()
}
}
func (this *Logger) Info(args ...interface{}) {
this.logPrint(L_INFO, args...)
}
func (this *Logger) Infoln(args ...interface{}) {
this.logPrintln(L_INFO, args...)
}
func (this *Logger) Infof(format string, args ...interface{}) {
this.logPrintf(L_INFO, format, args...)
}
func (this *Logger) Warning(args ...interface{}) {
this.logPrint(L_WARNING, args...)
}
func (this *Logger) Warningln(args ...interface{}) {
this.logPrintln(L_WARNING, args...)
}
func (this *Logger) Warningf(format string, args ...interface{}) {
this.logPrintf(L_WARNING, format, args...)
}
func (this *Logger) Debug(args ...interface{}) {
this.logPrint(L_DEBUG, args...)
this.Flush()
}
func (this *Logger) Debugln(args ...interface{}) {
this.logPrintln(L_DEBUG, args...)
this.Flush()
}
func (this *Logger) Debugf(format string, args ...interface{}) {
this.logPrintf(L_DEBUG, format, args...)
this.Flush()
}