1 Star 0 Fork 0

庸人妄语 / go-log

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
writer.go 4.67 KB
一键复制 编辑 原始数据 按行查看 历史
庸人妄语 提交于 2023-08-14 15:39 . 与标准库统一日志接口
package log
import (
"bufio"
"errors"
"io"
"os"
)
type LogWriter interface {
io.Writer
//获取可写日志类型
GetLevels() Levels
//判断是否写入
IsWrite(lv Level) bool
//写日志
WriteLog(lv Level, content []byte)
//关闭
io.Closer
}
type WriterErrHandler func(w LogWriter, e error, log string)
type logWriterOptions struct {
lvs Levels //输出的日志类型
w io.Writer //输出的接口
errHandle WriterErrHandler //输出失败消息回调
}
type LogWriterOption func(*logWriterOptions)
func LWLevel(lv Levels) LogWriterOption {
return func(w *logWriterOptions) {
w.lvs = lv
}
}
func LWStrLevel(lv string) LogWriterOption {
return func(w *logWriterOptions) {
w.lvs = NewLevel(lv)
}
}
func LWithWriter(writer io.Writer) LogWriterOption {
return func(w *logWriterOptions) {
w.w = writer
}
}
func LWErrHandler(eh WriterErrHandler) LogWriterOption {
return func(w *logWriterOptions) {
w.errHandle = eh
}
}
var defaultLogWriterOptions = logWriterOptions{
lvs: Lv_Debug,
errHandle: func(LogWriter, error, string) {},
}
// 控制台输出
func NewConsoleWriter(opts ...LogWriterOption) LogWriter {
opts = append(opts, LWithWriter(os.Stdout))
return NewLogWriter(opts...)
}
// 输出日志
type logWriter struct {
opts logWriterOptions
}
func NewLogWriter(opts ...LogWriterOption) LogWriter {
w := &logWriter{
opts: defaultLogWriterOptions,
}
for _, opt := range opts {
opt(&w.opts)
}
return w
}
func (w *logWriter) GetLevels() Levels {
return w.opts.lvs
}
func (w *logWriter) IsWrite(lv Level) bool {
return w.opts.lvs.Enable(lv)
}
func (w *logWriter) Write(content []byte) (int, error) {
return w.opts.w.Write(content)
}
func (w *logWriter) WriteLog(lv Level, content []byte) {
if w.IsWrite(lv) {
_, err := w.Write(content)
if err != nil {
w.opts.errHandle(w, err, string(content))
}
}
}
func (w *logWriter) Close() error {
if clser, ok := w.opts.w.(io.Closer); ok {
return clser.Close()
}
return nil
}
// 多个输出终端
type MultiWriter struct {
writers []LogWriter
//需要保存的日志, 根据Writers的Level进行推断
lvs Levels
}
func NewMultiWriter(ws ...LogWriter) *MultiWriter {
l := NOLOG
for _, wr := range ws {
l |= wr.GetLevels()
}
return &MultiWriter{ws, l}
}
func (w *MultiWriter) GetLevels() Levels {
return w.lvs
}
func (w *MultiWriter) IsWrite(lv Level) bool {
return w.lvs.Enable(lv)
}
func (w *MultiWriter) Write(content []byte) (int, error) {
var r int
var e error
for _, wr := range w.writers {
r, e = wr.Write(content)
if e != nil {
break
}
}
return r, e
}
func (w *MultiWriter) WriteLog(lv Level, content []byte) {
for _, wr := range w.writers {
wr.WriteLog(lv, content)
}
}
func (w *MultiWriter) Close() error {
var err error
for _, wr := range w.writers {
e := wr.Close()
if e != nil {
err = e
}
}
return err
}
// 异步输出终端
type PipeWriter struct {
opts logWriterOptions
pw *io.PipeWriter
pr *io.PipeReader
}
func NewPipeWriter(opts ...LogWriterOption) *PipeWriter {
p := &PipeWriter{
opts: defaultLogWriterOptions,
}
for _, opt := range opts {
opt(&p.opts)
}
p.initPipe()
return p
}
func (w *PipeWriter) GetLevels() Levels {
return w.opts.lvs
}
func (w *PipeWriter) IsWrite(lv Level) bool {
return w.opts.lvs.Enable(lv)
}
func (w *PipeWriter) Write(content []byte) (int, error) {
return w.pw.Write(content)
}
func (w *PipeWriter) WriteLog(lv Level, content []byte) {
if w.IsWrite(lv) {
_, err := w.pw.Write(content)
if err != nil {
if !errors.Is(err, io.ErrClosedPipe) {
w.opts.errHandle(w, err, string(content))
}
}
}
}
func (w *PipeWriter) Close() error {
return w.pw.Close()
}
func (w *PipeWriter) initPipe() {
if w.pw != nil {
w.pw.Close()
}
if w.pr != nil {
w.scanmsg()
}
pr, pw := io.Pipe()
w.pr = pr
w.pw = pw
go w.readmsg()
}
func (w *PipeWriter) closeReader() {
if w.pr != nil {
w.pr.Close()
w.pr = nil
if clser, ok := w.opts.w.(io.Closer); ok {
clser.Close()
}
}
}
func (w *PipeWriter) readmsg() {
defer w.closeReader()
buf := make([]byte, 4096)
for {
s, err := w.pr.Read(buf[:4096])
if err != nil {
if errors.Is(err, io.EOF) {
break
}
w.opts.errHandle(w, err, "")
break
}
_, err = w.opts.w.Write(buf[:s])
if err != nil {
w.opts.errHandle(w, err, string(buf[:s]))
}
}
}
func (w *PipeWriter) scanmsg() {
defer w.closeReader()
scanner := bufio.NewScanner(w.pr)
scanner.Split(bufio.ScanRunes)
for scanner.Scan() {
buf := scanner.Bytes()
_, err := w.opts.w.Write(buf)
if err != nil {
w.opts.errHandle(w, err, string(buf))
}
}
if err := scanner.Err(); err != nil && errors.Is(err, io.EOF) {
w.opts.errHandle(w, err, "")
}
}
Go
1
https://gitee.com/yrwy/go-log.git
git@gitee.com:yrwy/go-log.git
yrwy
go-log
go-log
v0.0.4

搜索帮助

53164aa7 5694891 3bd8fe86 5694891