Skip to content

Commit

Permalink
Merge pull request #2 from muir/one
Browse files Browse the repository at this point in the history
refactor: combining base loggers is now outside Logger
  • Loading branch information
muir authored Jul 9, 2022
2 parents 5d10a40 + 7795e22 commit 3dfdce2
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 175 deletions.
31 changes: 15 additions & 16 deletions base.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package xoplog

import (
"github.com/muir/xoplog/trace"
"github.com/muir/xoplog/internal/multibase"
"github.com/muir/xoplog/xopbase"
"github.com/muir/xoplog/xopconst"
)

type baseLoggers struct {
AsOne xopbase.Logger
List []baseLogger
Removed []baseLogger
}
Expand All @@ -17,19 +18,7 @@ type baseLogger struct {
MinLevel xopconst.Level
}

func (s baseLoggers) requests(bundle trace.Bundle) (xopbase.Requests, bool) {
baseRequests := make(xopbase.Requests, len(s.List))
var referencesKept bool
for i, baseLogger := range s.List {
baseRequests[i] = baseLogger.Base.Request(bundle)
if baseLogger.Base.ReferencesKept() {
referencesKept = true
}
}
return baseRequests, referencesKept
}

func (s baseLoggers) copyWithoutTrace() baseLoggers {
func (s baseLoggers) Copy() baseLoggers {
n := make([]baseLogger, len(s.List))
for i, bl := range s.List {
n[i] = baseLogger{
Expand All @@ -38,7 +27,8 @@ func (s baseLoggers) copyWithoutTrace() baseLoggers {
}
}
return baseLoggers{
List: n,
AsOne: s.AsOne,
List: n,
}
}

Expand All @@ -52,17 +42,26 @@ func WithoutBaseLogger(name string) SeedModifier {
s.baseLoggers.List[len(s.baseLoggers.List)-1], s.baseLoggers.List[i]
}
s.baseLoggers.List = s.baseLoggers.List[:len(s.baseLoggers.List)-1]
break
s.rebuildAsOne()
}
}
}
}

func (s *Seed) rebuildAsOne() {
loggers := make([]xopbase.Logger, len(s.baseLoggers.List))
for i, baseLogger := range s.baseLoggers.List {
loggers[i] = baseLogger.Base
}
s.baseLoggers.AsOne = multibase.CombineLoggers(loggers)
}

func WithBaseLogger(name string, logger xopbase.Logger) SeedModifier {
return func(s *Seed) {
s.baseLoggers.List = append(s.baseLoggers.List, baseLogger{
Name: name,
Base: logger,
})
s.rebuildAsOne()
}
}
173 changes: 173 additions & 0 deletions internal/multibase/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package multibase

import (
"sync"
"time"

"github.com/muir/xoplog/trace"
"github.com/muir/xoplog/xop"
"github.com/muir/xoplog/xopbase"
"github.com/muir/xoplog/xopconst"
)

type Loggers []xopbase.Logger
type Requests []xopbase.Request
type Spans []xopbase.Span
type Lines []xopbase.Line

var _ xopbase.Logger = Loggers{}
var _ xopbase.Request = Requests{}
var _ xopbase.Span = Spans{}
var _ xopbase.Line = Lines{}

func CombineLoggers(loggers []xopbase.Logger) xopbase.Logger {
if len(loggers) == 1 {
return loggers[0]
}
return Loggers(loggers)
}

func (l Loggers) Request(span trace.Bundle) xopbase.Request {
r := make(Requests, len(l))
for i, logger := range l {
r[i] = logger.Request(span)
}
return r
}

func (l Loggers) ReferencesKept() bool {
for _, logger := range l {
if logger.ReferencesKept() {
return true
}
}
return false
}

func (l Loggers) Close() {
for _, logger := range l {
logger.Close()
}
}

func (s Requests) Flush() {
var wg sync.WaitGroup
wg.Add(len(s))
for _, request := range s {
go func() {
defer wg.Done()
request.Flush()
}()
}
wg.Wait()
}

func (s Requests) Span(span trace.Bundle) xopbase.Span {
spans := make(Spans, len(s))
for i, ele := range s {
spans[i] = ele.Span(span)
}
return spans
}
func (s Spans) Span(span trace.Bundle) xopbase.Span {
spans := make(Spans, len(s))
for i, ele := range s {
spans[i] = ele.Span(span)
}
return spans
}

func (s Requests) SpanInfo(st xopconst.SpanType, things []xop.Thing) {
for _, span := range s {
span.SpanInfo(st, things)
}
}
func (s Spans) SpanInfo(st xopconst.SpanType, things []xop.Thing) {
for _, span := range s {
span.SpanInfo(st, things)
}
}

func (s Requests) AddPrefill(things []xop.Thing) {
for _, span := range s {
span.AddPrefill(things)
}
}
func (s Spans) AddPrefill(things []xop.Thing) {
for _, span := range s {
span.AddPrefill(things)
}
}

func (s Requests) ResetLinePrefill() {
for _, span := range s {
span.ResetLinePrefill()
}
}
func (s Spans) ResetLinePrefill() {
for _, span := range s {
span.ResetLinePrefill()
}
}

func (s Requests) Line(level xopconst.Level, t time.Time) xopbase.Line {
lines := make(Lines, len(s))
for i, span := range s {
lines[i] = span.Line(level, t)
}
return lines
}
func (s Spans) Line(level xopconst.Level, t time.Time) xopbase.Line {
lines := make(Lines, len(s))
for i, span := range s {
lines[i] = span.Line(level, t)
}
return lines
}

func (l Lines) Int(k string, v int64) {
for _, line := range l {
line.Int(k, v)
}
}
func (l Lines) Str(k string, v string) {
for _, line := range l {
line.Str(k, v)
}
}
func (l Lines) Bool(k string, v bool) {
for _, line := range l {
line.Bool(k, v)
}
}
func (l Lines) Uint(k string, v uint64) {
for _, line := range l {
line.Uint(k, v)
}
}
func (l Lines) Time(k string, v time.Time) {
for _, line := range l {
line.Time(k, v)
}
}
func (l Lines) Any(k string, v interface{}) {
for _, line := range l {
line.Any(k, v)
}
}
func (l Lines) Error(k string, v error) {
for _, line := range l {
line.Error(k, v)
}
}
func (l Lines) Msg(m string) {
for _, line := range l {
line.Msg(m)
}
}

func (l Lines) Things(things []xop.Thing) {
for _, line := range l {
xopbase.LineThings(line, things)
}
}
76 changes: 36 additions & 40 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ type Log struct {
}

type Span struct {
seed Seed
dataLock sync.Mutex // protects Data & SpanType (can only be held for short periods)
data []xop.Thing
spanType xopconst.SpanType
log *Log // back to self
baseSpans xopbase.Spans
seed Seed
dataLock sync.Mutex // protects Data & SpanType (can only be held for short periods)
data []xop.Thing
spanType xopconst.SpanType
log *Log // back to self
base xopbase.Span
}

type local struct {
Expand All @@ -47,7 +47,7 @@ type shared struct {
FlushTimer *time.Timer
FlushDelay time.Duration
FlushActive int32 // 1 == timer is running, 0 = timer is not running
BaseRequests xopbase.Requests
BaseRequest xopbase.Request
ReferencesKept bool

// Dirty holds spans that have modified data and need to be
Expand Down Expand Up @@ -79,8 +79,9 @@ func (s Seed) Request(description string) *Log {
log.request = &log.span
log.shared.Dirty = append(log.shared.Dirty, &log)
log.shared.FlushTimer = time.AfterFunc(DefaultFlushDelay, log.timerFlush)
log.shared.BaseRequests, log.shared.ReferencesKept = log.span.seed.baseLoggers.requests(log.span.seed.traceBundle)
log.span.baseSpans = log.shared.BaseRequests.Spans()
log.shared.BaseRequest = log.span.seed.baseLoggers.AsOne.Request(log.span.seed.traceBundle)
log.shared.ReferencesKept = log.span.seed.baseLoggers.AsOne.ReferencesKept()
log.span.base = log.shared.BaseRequest.(xopbase.Span)
return &log
}

Expand Down Expand Up @@ -150,20 +151,15 @@ func (l *Log) Flush() {
l.shared.FlushLock.Lock()
defer l.shared.FlushLock.Unlock()
for _, log := range dirty {
for _, baseSpan := range log.span.baseSpans {
baseSpan.SpanInfo(log.span.spanType, log.span.data)
}
log.span.base.SpanInfo(log.span.spanType, log.span.data)
}
l.shared.BaseRequests.Flush()
l.shared.BaseRequest.Flush()
}

func (l *Log) log(level xopconst.Level, msg string, values []xop.Thing) {
t := time.Now()
for _, baseSpan := range l.span.baseSpans {
line := baseSpan.Line(level, t)
xopbase.LineThings(line, values)
line.Msg(msg)
}
line := l.span.base.Line(level, time.Now())
xopbase.LineThings(line, values)
line.Msg(msg)
l.enableFlushTimer()
}

Expand Down Expand Up @@ -247,15 +243,15 @@ func (l *Log) LogThings(level xopconst.Level, msg string, values ...xop.Thing) {
}

type LogLine struct {
log *Log
lines xopbase.Lines
log *Log
line xopbase.Line
}

func (l *Log) LogLine(level xopconst.Level) LogLine {
// TODO PERFORMANCE: have a sync.Pool of LogLines
return LogLine{
log: l,
lines: l.span.baseSpans.Line(level, time.Now()),
log: l,
line: l.span.base.Line(level, time.Now()),
}
}

Expand All @@ -268,27 +264,27 @@ func (l *Log) Alert() LogLine { return l.LogLine(xopconst.AlertLevel) }

// TODO: generate these
// TODO: the rest of the set
func (ll LogLine) Msg(msg string) { ll.lines.Msg(msg); ll.log.enableFlushTimer() }
func (ll LogLine) Msg(msg string) { ll.line.Msg(msg); ll.log.enableFlushTimer() }
func (ll LogLine) Msgf(msg string, v ...interface{}) { ll.Msg(fmt.Sprintf(msg, v...)) }
func (ll LogLine) Msgs(v ...interface{}) { ll.Msg(fmt.Sprint(v...)) }
func (ll LogLine) Int(k string, v int) LogLine { ll.lines.Int(k, int64(v)); return ll }
func (ll LogLine) Int8(k string, v int8) LogLine { ll.lines.Int(k, int64(v)); return ll }
func (ll LogLine) Int16(k string, v int16) LogLine { ll.lines.Int(k, int64(v)); return ll }
func (ll LogLine) Int32(k string, v int32) LogLine { ll.lines.Int(k, int64(v)); return ll }
func (ll LogLine) Int64(k string, v int64) LogLine { ll.lines.Int(k, v); return ll }
func (ll LogLine) Uint(k string, v uint) LogLine { ll.lines.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint8(k string, v uint8) LogLine { ll.lines.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint16(k string, v uint16) LogLine { ll.lines.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint32(k string, v uint32) LogLine { ll.lines.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint64(k string, v uint64) LogLine { ll.lines.Uint(k, v); return ll }
func (ll LogLine) Str(k string, v string) LogLine { ll.lines.Str(k, v); return ll }
func (ll LogLine) Bool(k string, v bool) LogLine { ll.lines.Bool(k, v); return ll }
func (ll LogLine) Time(k string, v time.Time) LogLine { ll.lines.Time(k, v); return ll }
func (ll LogLine) Error(k string, v error) LogLine { ll.lines.Error(k, v); return ll }
func (ll LogLine) Int(k string, v int) LogLine { ll.line.Int(k, int64(v)); return ll }
func (ll LogLine) Int8(k string, v int8) LogLine { ll.line.Int(k, int64(v)); return ll }
func (ll LogLine) Int16(k string, v int16) LogLine { ll.line.Int(k, int64(v)); return ll }
func (ll LogLine) Int32(k string, v int32) LogLine { ll.line.Int(k, int64(v)); return ll }
func (ll LogLine) Int64(k string, v int64) LogLine { ll.line.Int(k, v); return ll }
func (ll LogLine) Uint(k string, v uint) LogLine { ll.line.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint8(k string, v uint8) LogLine { ll.line.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint16(k string, v uint16) LogLine { ll.line.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint32(k string, v uint32) LogLine { ll.line.Uint(k, uint64(v)); return ll }
func (ll LogLine) Uint64(k string, v uint64) LogLine { ll.line.Uint(k, v); return ll }
func (ll LogLine) Str(k string, v string) LogLine { ll.line.Str(k, v); return ll }
func (ll LogLine) Bool(k string, v bool) LogLine { ll.line.Bool(k, v); return ll }
func (ll LogLine) Time(k string, v time.Time) LogLine { ll.line.Time(k, v); return ll }
func (ll LogLine) Error(k string, v error) LogLine { ll.line.Error(k, v); return ll }

// AnyImmutable can be used to log something that is not going to be further modified
// after this call.
func (ll LogLine) AnyImmutable(k string, v interface{}) LogLine { ll.lines.Any(k, v); return ll }
func (ll LogLine) AnyImmutable(k string, v interface{}) LogLine { ll.line.Any(k, v); return ll }

// Any can be used to log something that might be modified after this call. If any base
// logger does not immediately serialize, then the object will be copied using
Expand All @@ -298,7 +294,7 @@ func (ll LogLine) Any(k string, v interface{}) LogLine {
// TODO: make copy function configurable
v = deepcopy.Copy(v)
}
ll.lines.Any(k, v)
ll.line.Any(k, v)
return ll
}

Expand Down
Loading

0 comments on commit 3dfdce2

Please sign in to comment.