269 lines
4.8 KiB
Go
269 lines
4.8 KiB
Go
|
|
package starlog
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
|
||
|
|
"b612.me/starlog/internal/observerx"
|
||
|
|
)
|
||
|
|
|
||
|
|
type Observer struct {
|
||
|
|
buffer *observerx.Buffer
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) ensureBuffer() *observerx.Buffer {
|
||
|
|
if observer == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
if observer.buffer == nil {
|
||
|
|
observer.buffer = observerx.NewBuffer()
|
||
|
|
}
|
||
|
|
return observer.buffer
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewObserver() *Observer {
|
||
|
|
return &Observer{
|
||
|
|
buffer: observerx.NewBuffer(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewObserverWithLimit(limit int) *Observer {
|
||
|
|
observer := NewObserver()
|
||
|
|
observer.SetLimit(limit)
|
||
|
|
return observer
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) Handle(ctx context.Context, entry *Entry) error {
|
||
|
|
_ = ctx
|
||
|
|
if observer == nil || entry == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
entryCopy := *entry
|
||
|
|
entryCopy.Fields = cloneFields(entry.Fields)
|
||
|
|
buffer.Add(entryCopy)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) SetLimit(limit int) {
|
||
|
|
if observer == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
buffer.SetLimit(limit)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) Limit() int {
|
||
|
|
if observer == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return buffer.Limit()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) Count() int {
|
||
|
|
if observer == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return buffer.Count()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) Dropped() uint64 {
|
||
|
|
if observer == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return buffer.Dropped()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) Entries() []Entry {
|
||
|
|
if observer == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
items := buffer.Snapshot()
|
||
|
|
result := make([]Entry, 0, len(items))
|
||
|
|
for _, raw := range items {
|
||
|
|
entry, ok := raw.(Entry)
|
||
|
|
if !ok {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
item := entry
|
||
|
|
item.Fields = cloneFields(entry.Fields)
|
||
|
|
result = append(result, item)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) Last() (Entry, bool) {
|
||
|
|
if observer == nil {
|
||
|
|
return Entry{}, false
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return Entry{}, false
|
||
|
|
}
|
||
|
|
raw, ok := buffer.Last()
|
||
|
|
if !ok {
|
||
|
|
return Entry{}, false
|
||
|
|
}
|
||
|
|
entry, ok := raw.(Entry)
|
||
|
|
if !ok {
|
||
|
|
return Entry{}, false
|
||
|
|
}
|
||
|
|
entry.Fields = cloneFields(entry.Fields)
|
||
|
|
return entry, true
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) TakeAll() []Entry {
|
||
|
|
if observer == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
items := buffer.TakeAll()
|
||
|
|
if len(items) == 0 {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
result := make([]Entry, 0, len(items))
|
||
|
|
for _, raw := range items {
|
||
|
|
entry, ok := raw.(Entry)
|
||
|
|
if !ok {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
item := entry
|
||
|
|
item.Fields = cloneFields(entry.Fields)
|
||
|
|
result = append(result, item)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func (observer *Observer) Reset() {
|
||
|
|
if observer == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
buffer := observer.ensureBuffer()
|
||
|
|
if buffer == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
buffer.Reset()
|
||
|
|
}
|
||
|
|
|
||
|
|
type testHookHandler struct {
|
||
|
|
observer *Observer
|
||
|
|
next Handler
|
||
|
|
}
|
||
|
|
|
||
|
|
func (handler *testHookHandler) Handle(ctx context.Context, entry *Entry) error {
|
||
|
|
if handler == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
var firstErr error
|
||
|
|
if handler.observer != nil {
|
||
|
|
if err := handler.observer.Handle(ctx, entry); err != nil && firstErr == nil {
|
||
|
|
firstErr = err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if handler.next != nil {
|
||
|
|
if err := handler.next.Handle(ctx, entry); err != nil && firstErr == nil {
|
||
|
|
firstErr = err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return firstErr
|
||
|
|
}
|
||
|
|
|
||
|
|
type TestHook struct {
|
||
|
|
logger *StarLogger
|
||
|
|
observer *Observer
|
||
|
|
previous Handler
|
||
|
|
handler Handler
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewTestHook(logger *StarLogger) *TestHook {
|
||
|
|
if logger == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
observer := NewObserver()
|
||
|
|
previous := logger.GetEntryHandler()
|
||
|
|
wrapper := &testHookHandler{
|
||
|
|
observer: observer,
|
||
|
|
next: previous,
|
||
|
|
}
|
||
|
|
logger.SetEntryHandler(wrapper)
|
||
|
|
return &TestHook{
|
||
|
|
logger: logger,
|
||
|
|
observer: observer,
|
||
|
|
previous: previous,
|
||
|
|
handler: wrapper,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (hook *TestHook) Observer() *Observer {
|
||
|
|
if hook == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
return hook.observer
|
||
|
|
}
|
||
|
|
|
||
|
|
func (hook *TestHook) Entries() []Entry {
|
||
|
|
if hook == nil || hook.observer == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
return hook.observer.Entries()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (hook *TestHook) Count() int {
|
||
|
|
if hook == nil || hook.observer == nil {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return hook.observer.Count()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (hook *TestHook) Last() (Entry, bool) {
|
||
|
|
if hook == nil || hook.observer == nil {
|
||
|
|
return Entry{}, false
|
||
|
|
}
|
||
|
|
return hook.observer.Last()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (hook *TestHook) Reset() {
|
||
|
|
if hook == nil || hook.observer == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
hook.observer.Reset()
|
||
|
|
}
|
||
|
|
|
||
|
|
// Close tries to restore the previous entry handler.
|
||
|
|
// It returns false when current handler was replaced externally.
|
||
|
|
func (hook *TestHook) Close() bool {
|
||
|
|
if hook == nil || hook.logger == nil {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
current := hook.logger.GetEntryHandler()
|
||
|
|
if current != hook.handler {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
hook.logger.SetEntryHandler(hook.previous)
|
||
|
|
return true
|
||
|
|
}
|