mirror of
https://github.com/nshttpd/mikrotik-exporter.git
synced 2024-12-11 14:18:28 +01:00
175 lines
4.9 KiB
Go
175 lines
4.9 KiB
Go
// Copyright (c) 2016 Uber Technologies, Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
// Package observer provides a zapcore.Core that keeps an in-memory,
|
|
// encoding-agnostic repesentation of log entries. It's useful for
|
|
// applications that want to unit test their log output without tying their
|
|
// tests to a particular output encoding.
|
|
package observer // import "go.uber.org/zap/zaptest/observer"
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
// An LoggedEntry is an encoding-agnostic representation of a log message.
|
|
// Field availability is context dependant.
|
|
type LoggedEntry struct {
|
|
zapcore.Entry
|
|
Context []zapcore.Field
|
|
}
|
|
|
|
// ObservedLogs is a concurrency-safe, ordered collection of observed logs.
|
|
type ObservedLogs struct {
|
|
mu sync.RWMutex
|
|
logs []LoggedEntry
|
|
}
|
|
|
|
// Len returns the number of items in the collection.
|
|
func (o *ObservedLogs) Len() int {
|
|
o.mu.RLock()
|
|
n := len(o.logs)
|
|
o.mu.RUnlock()
|
|
return n
|
|
}
|
|
|
|
// All returns a copy of all the observed logs.
|
|
func (o *ObservedLogs) All() []LoggedEntry {
|
|
o.mu.RLock()
|
|
ret := make([]LoggedEntry, len(o.logs))
|
|
for i := range o.logs {
|
|
ret[i] = o.logs[i]
|
|
}
|
|
o.mu.RUnlock()
|
|
return ret
|
|
}
|
|
|
|
// TakeAll returns a copy of all the observed logs, and truncates the observed
|
|
// slice.
|
|
func (o *ObservedLogs) TakeAll() []LoggedEntry {
|
|
o.mu.Lock()
|
|
ret := o.logs
|
|
o.logs = nil
|
|
o.mu.Unlock()
|
|
return ret
|
|
}
|
|
|
|
// AllUntimed returns a copy of all the observed logs, but overwrites the
|
|
// observed timestamps with time.Time's zero value. This is useful when making
|
|
// assertions in tests.
|
|
func (o *ObservedLogs) AllUntimed() []LoggedEntry {
|
|
ret := o.All()
|
|
for i := range ret {
|
|
ret[i].Time = time.Time{}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// FilterMessage filters entries to those that have the specified message.
|
|
func (o *ObservedLogs) FilterMessage(msg string) *ObservedLogs {
|
|
return o.filter(func(e LoggedEntry) bool {
|
|
return e.Message == msg
|
|
})
|
|
}
|
|
|
|
// FilterMessageSnippet filters entries to those that have a message containing the specified snippet.
|
|
func (o *ObservedLogs) FilterMessageSnippet(snippet string) *ObservedLogs {
|
|
return o.filter(func(e LoggedEntry) bool {
|
|
return strings.Contains(e.Message, snippet)
|
|
})
|
|
}
|
|
|
|
// FilterField filters entries to those that have the specified field.
|
|
func (o *ObservedLogs) FilterField(field zapcore.Field) *ObservedLogs {
|
|
return o.filter(func(e LoggedEntry) bool {
|
|
for _, ctxField := range e.Context {
|
|
if ctxField.Equals(field) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
})
|
|
}
|
|
|
|
func (o *ObservedLogs) filter(match func(LoggedEntry) bool) *ObservedLogs {
|
|
o.mu.RLock()
|
|
defer o.mu.RUnlock()
|
|
|
|
var filtered []LoggedEntry
|
|
for _, entry := range o.logs {
|
|
if match(entry) {
|
|
filtered = append(filtered, entry)
|
|
}
|
|
}
|
|
return &ObservedLogs{logs: filtered}
|
|
}
|
|
|
|
func (o *ObservedLogs) add(log LoggedEntry) {
|
|
o.mu.Lock()
|
|
o.logs = append(o.logs, log)
|
|
o.mu.Unlock()
|
|
}
|
|
|
|
// New creates a new Core that buffers logs in memory (without any encoding).
|
|
// It's particularly useful in tests.
|
|
func New(enab zapcore.LevelEnabler) (zapcore.Core, *ObservedLogs) {
|
|
ol := &ObservedLogs{}
|
|
return &contextObserver{
|
|
LevelEnabler: enab,
|
|
logs: ol,
|
|
}, ol
|
|
}
|
|
|
|
type contextObserver struct {
|
|
zapcore.LevelEnabler
|
|
logs *ObservedLogs
|
|
context []zapcore.Field
|
|
}
|
|
|
|
func (co *contextObserver) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
|
|
if co.Enabled(ent.Level) {
|
|
return ce.AddCore(ent, co)
|
|
}
|
|
return ce
|
|
}
|
|
|
|
func (co *contextObserver) With(fields []zapcore.Field) zapcore.Core {
|
|
return &contextObserver{
|
|
LevelEnabler: co.LevelEnabler,
|
|
logs: co.logs,
|
|
context: append(co.context[:len(co.context):len(co.context)], fields...),
|
|
}
|
|
}
|
|
|
|
func (co *contextObserver) Write(ent zapcore.Entry, fields []zapcore.Field) error {
|
|
all := make([]zapcore.Field, 0, len(fields)+len(co.context))
|
|
all = append(all, co.context...)
|
|
all = append(all, fields...)
|
|
co.logs.add(LoggedEntry{ent, all})
|
|
return nil
|
|
}
|
|
|
|
func (co *contextObserver) Sync() error {
|
|
return nil
|
|
}
|