mirror of https://github.com/gogs/gogs.git
142 lines
3.3 KiB
Go
142 lines
3.3 KiB
Go
// 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 clog
|
|
|
|
import "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
|
|
}
|
|
}
|