mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.3 KiB
141 lines
3.3 KiB
// 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 |
|
} |
|
}
|
|
|