mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
131 lines
3.2 KiB
Go
131 lines
3.2 KiB
Go
// Copyright 2013, Cong Ding. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
// author: Cong Ding <dinggnu@gmail.com>
|
|
//
|
|
package logging
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// watcher watches the logger.queue channel, and writes the logs to output
|
|
func (logger *Logger) watcher() {
|
|
var buf bytes.Buffer
|
|
for {
|
|
timeout := time.After(time.Second / 10)
|
|
|
|
for i := 0; i < bufSize; i++ {
|
|
select {
|
|
case msg := <-logger.queue:
|
|
fmt.Fprintln(&buf, msg)
|
|
case req := <-logger.request:
|
|
logger.flushReq(&buf, &req)
|
|
case <-timeout:
|
|
i = bufSize
|
|
case <-logger.flush:
|
|
logger.flushBuf(&buf)
|
|
logger.flush <- true
|
|
i = bufSize
|
|
case <-logger.quit:
|
|
// If quit signal received, cleans the channel
|
|
// and writes all of them to io.Writer.
|
|
for {
|
|
select {
|
|
case msg := <-logger.queue:
|
|
fmt.Fprintln(&buf, msg)
|
|
case req := <-logger.request:
|
|
logger.flushReq(&buf, &req)
|
|
case <-logger.flush:
|
|
// do nothing
|
|
default:
|
|
logger.flushBuf(&buf)
|
|
logger.quit <- true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
logger.flushBuf(&buf)
|
|
}
|
|
}
|
|
|
|
// flushBuf flushes the content of buffer to out and reset the buffer
|
|
func (logger *Logger) flushBuf(b *bytes.Buffer) {
|
|
if len(b.Bytes()) > 0 {
|
|
logger.out.Write(b.Bytes())
|
|
b.Reset()
|
|
}
|
|
}
|
|
|
|
// flushReq handles the request and writes the result to writer
|
|
func (logger *Logger) flushReq(b *bytes.Buffer, req *request) {
|
|
if req.format == "" {
|
|
msg := fmt.Sprint(req.v...)
|
|
msg = logger.genLog(req.level, msg)
|
|
fmt.Fprintln(b, msg)
|
|
} else {
|
|
msg := fmt.Sprintf(req.format, req.v...)
|
|
msg = logger.genLog(req.level, msg)
|
|
fmt.Fprintln(b, msg)
|
|
}
|
|
}
|
|
|
|
// flushMsg is to print log to file, stdout, or others.
|
|
func (logger *Logger) flushMsg(message string) {
|
|
if logger.sync {
|
|
logger.wlock.Lock()
|
|
defer logger.wlock.Unlock()
|
|
fmt.Fprintln(logger.out, message)
|
|
} else {
|
|
logger.queue <- message
|
|
}
|
|
}
|
|
|
|
// log records log v... with level `level'.
|
|
func (logger *Logger) log(level Level, v ...interface{}) {
|
|
if int32(level) >= atomic.LoadInt32((*int32)(&logger.level)) {
|
|
if logger.runtime || logger.sync {
|
|
message := fmt.Sprint(v...)
|
|
message = logger.genLog(level, message)
|
|
logger.flushMsg(message)
|
|
} else {
|
|
r := new(request)
|
|
r.level = level
|
|
r.v = v
|
|
logger.request <- *r
|
|
}
|
|
}
|
|
}
|
|
|
|
// logf records log v... with level `level'.
|
|
func (logger *Logger) logf(level Level, format string, v ...interface{}) {
|
|
if int32(level) >= atomic.LoadInt32((*int32)(&logger.level)) {
|
|
if logger.runtime || logger.sync {
|
|
message := fmt.Sprintf(format, v...)
|
|
message = logger.genLog(level, message)
|
|
logger.flushMsg(message)
|
|
} else {
|
|
r := new(request)
|
|
r.level = level
|
|
r.format = format
|
|
r.v = v
|
|
logger.request <- *r
|
|
}
|
|
}
|
|
}
|