| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 | // Copyright 2017 Unknwon//// 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.package clogimport "fmt"// Logger is an interface for a logger adapter with specific mode and level.type Logger interface {	// Level returns minimum level of given logger.	Level() LEVEL	// Init accepts a config struct specific for given logger and performs any necessary initialization.	Init(interface{}) error	// ExchangeChans accepts error channel, and returns message receive channel.	ExchangeChans(chan<- error) chan *Message	// Start starts message processing.	Start()	// Destroy releases all resources.	Destroy()}// Adapter contains common fields for any logger adapter. This struct should be used as embedded struct.type Adapter struct {	level     LEVEL	msgChan   chan *Message	quitChan  chan struct{}	errorChan chan<- error}type Factory func() Logger// factories keeps factory function of registered loggers.var factories = map[MODE]Factory{}func Register(mode MODE, f Factory) {	if f == nil {		panic("clog: register function is nil")	}	if factories[mode] != nil {		panic("clog: register duplicated mode '" + mode + "'")	}	factories[mode] = f}type receiver struct {	Logger	mode    MODE	msgChan chan *Message}var (	// receivers is a list of loggers with their message channel for broadcasting.	receivers []*receiver	errorChan = make(chan error, 5)	quitChan  = make(chan struct{}))func init() {	// Start background error handling goroutine.	go func() {		for {			select {			case err := <-errorChan:				fmt.Printf("clog: unable to write message: %v\n", err)			case <-quitChan:				return			}		}	}()}// New initializes and appends a new logger to the receiver list.// Calling this function multiple times will overwrite previous logger with same mode.func New(mode MODE, cfg interface{}) error {	factory, ok := factories[mode]	if !ok {		return fmt.Errorf("unknown mode '%s'", mode)	}	logger := factory()	if err := logger.Init(cfg); err != nil {		return err	}	msgChan := logger.ExchangeChans(errorChan)	// Check and replace previous logger.	hasFound := false	for i := range receivers {		if receivers[i].mode == mode {			hasFound = true			// Release previous logger.			receivers[i].Destroy()			// Update info to new one.			receivers[i].Logger = logger			receivers[i].msgChan = msgChan			break		}	}	if !hasFound {		receivers = append(receivers, &receiver{			Logger:  logger,			mode:    mode,			msgChan: msgChan,		})	}	go logger.Start()	return nil}// Delete removes logger from the receiver list.func Delete(mode MODE) {	foundIdx := -1	for i := range receivers {		if receivers[i].mode == mode {			foundIdx = i			receivers[i].Destroy()		}	}	if foundIdx >= 0 {		newList := make([]*receiver, len(receivers)-1)		copy(newList, receivers[:foundIdx])		copy(newList[foundIdx:], receivers[foundIdx+1:])		receivers = newList	}}
 |