Skip to content
This repository has been archived by the owner on Feb 21, 2023. It is now read-only.

Commit

Permalink
Change API to use an attr builder instead of a direct map.
Browse files Browse the repository at this point in the history
  • Loading branch information
aphistic committed Aug 16, 2016
1 parent 66ad28a commit f7cb252
Show file tree
Hide file tree
Showing 18 changed files with 423 additions and 438 deletions.
87 changes: 87 additions & 0 deletions attrs.go
Original file line number Diff line number Diff line change
@@ -0,0 1,87 @@
package gomol

import (
"github.com/spaolacci/murmur3"

"fmt"
)

type Attrs struct {
attrs map[uint32]interface{}
}

func NewAttrs() *Attrs {
return &Attrs{
attrs: make(map[uint32]interface{}),
}
}

func (a *Attrs) mergeAttrs(attrs *Attrs) {
if attrs == nil {
return
}
for hash, val := range attrs.attrs {
a.attrs[hash] = val
}
}

func (a *Attrs) clone() *Attrs {
attrs := NewAttrs()
for hash, val := range a.attrs {
attrs.attrs[hash] = val
}
return attrs
}

func (a *Attrs) SetAttr(key string, value interface{}) *Attrs {
a.attrs[getAttrHash(key)] = value
return a
}

func (a *Attrs) GetAttr(key string) interface{} {
return a.attrs[getAttrHash(key)]
}

func (a *Attrs) RemoveAttr(key string) {
delete(a.attrs, getAttrHash(key))
}

func (a *Attrs) Attrs() map[string]interface{} {
attrs := make(map[string]interface{})
for hash, val := range a.attrs {
key, _ := getHashAttr(hash)
attrs[key] = val
}
return attrs
}

type logAttr struct {
Name string
Value interface{}
}

var attrHashes = make(map[string]uint32)
var hashAttrs = make(map[uint32]string)

func getAttrHash(attr string) uint32 {
if hash, ok := attrHashes[attr]; ok {
return hash
}

hasher := murmur3.New32()
hasher.Write([]byte(attr))

hash := hasher.Sum32()
hashAttrs[hash] = attr
attrHashes[attr] = hash

return hash
}

func getHashAttr(hash uint32) (string, error) {
if attr, ok := hashAttrs[hash]; ok {
return attr, nil
}

return "", fmt.Errorf("Could not find attr for hash %v", hash)
}
13 changes: 13 additions & 0 deletions attrs_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 1,13 @@
package gomol

import . "gopkg.in/check.v1"

func (s *GomolSuite) BenchmarkAttrChaining(c *C) {
for idx := 0; idx < c.N; idx {
NewAttrs().
SetAttr("attr1", "val1").
SetAttr("attr2", "val2").
SetAttr("attr3", 3).
SetAttr("attr4", 4)
}
}
21 changes: 21 additions & 0 deletions attrs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 1,21 @@
package gomol

import . "gopkg.in/check.v1"

func (s *GomolSuite) TestAttrsMergeNilAttrs(c *C) {
attrs := NewAttrs()
attrs.mergeAttrs(nil)
}

func (s *GomolSuite) TestAttrsChaining(c *C) {
attrs := NewAttrs().
SetAttr("attr1", "val1").
SetAttr("attr2", "val2").
SetAttr("attr3", 3).
SetAttr("attr4", 4)

c.Check(attrs.attrs[getAttrHash("attr1")], Equals, "val1")
c.Check(attrs.attrs[getAttrHash("attr2")], Equals, "val2")
c.Check(attrs.attrs[getAttrHash("attr3")], Equals, 3)
c.Check(attrs.attrs[getAttrHash("attr4")], Equals, 4)
}
43 changes: 20 additions & 23 deletions base.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 13,7 @@ type Base struct {
queue *queue
logLevel LogLevel
loggers []Logger
BaseAttrs map[string]interface{}
BaseAttrs *Attrs
}

// NewBase creates a new instance of Base with default values set.
Expand All @@ -23,7 23,7 @@ func NewBase() *Base {
queue: newQueue(),
logLevel: LevelDebug,
loggers: make([]Logger, 0),
BaseAttrs: make(map[string]interface{}, 0),
BaseAttrs: NewAttrs(),
}
return b
}
Expand Down Expand Up @@ -166,54 166,51 @@ func (b *Base) ShutdownLoggers() error {
/*
NewLogAdapter creates a LogAdapter using Base to log messages
*/
func (b *Base) NewLogAdapter(attrs map[string]interface{}) *LogAdapter {
func (b *Base) NewLogAdapter(attrs *Attrs) *LogAdapter {
return newLogAdapter(b, attrs)
}

// ClearAttrs will remove all the attributes added to Base
func (b *Base) ClearAttrs() {
b.BaseAttrs = make(map[string]interface{}, 0)
b.BaseAttrs = NewAttrs()
}

/*
SetAttr will set the value for the attribute with the name key. If the key
already exists it will be overwritten with the new value.
*/
func (b *Base) SetAttr(key string, value interface{}) {
b.BaseAttrs[key] = value
b.BaseAttrs.SetAttr(key, value)
}

/*
GetAttr will return the current value for the given attribute key. If the key
isn't set this will return nil
*/
func (b *Base) GetAttr(key string) interface{} {
if val, ok := b.BaseAttrs[key]; ok {
return val
}
return nil
return b.BaseAttrs.GetAttr(key)
}

// RemoveAttr will remove the attribute with the name key.
func (b *Base) RemoveAttr(key string) {
delete(b.BaseAttrs, key)
b.BaseAttrs.RemoveAttr(key)
}

func (b *Base) log(level LogLevel, m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) log(level LogLevel, m *Attrs, msg string, a ...interface{}) error {
if !b.shouldLog(level) {
return nil
}

if len(b.config.FilenameAttr) > 0 || len(b.config.LineNumberAttr) > 0 {
file, line := getCallerInfo()
if m == nil {
m = make(map[string]interface{})
m = NewAttrs()
}
if len(b.config.FilenameAttr) > 0 {
m[b.config.FilenameAttr] = file
m.SetAttr(b.config.FilenameAttr, file)
}
if len(b.config.LineNumberAttr) > 0 {
m[b.config.LineNumberAttr] = line
m.SetAttr(b.config.LineNumberAttr, line)
}
}

Expand All @@ -232,7 229,7 @@ func (b *Base) Dbgf(msg string, a ...interface{}) error {
}

// Dbgm is a short-hand version of Debugm
func (b *Base) Dbgm(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Dbgm(m *Attrs, msg string, a ...interface{}) error {
return b.Debugm(m, msg, a...)
}

Expand All @@ -255,7 252,7 @@ the resulting message to all added loggers at LogLevel.LevelDebug. It will also
merge all attributes passed in m with any attributes added to Base and include them
with the message if the Logger supports it.
*/
func (b *Base) Debugm(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Debugm(m *Attrs, msg string, a ...interface{}) error {
return b.log(LevelDebug, m, msg, a...)
}

Expand All @@ -278,7 275,7 @@ the resulting message to all added loggers at LogLevel.LevelInfo. It will also
merge all attributes passed in m with any attributes added to Base and include them
with the message if the Logger supports it.
*/
func (b *Base) Infom(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Infom(m *Attrs, msg string, a ...interface{}) error {
return b.log(LevelInfo, m, msg, a...)
}

Expand All @@ -293,7 290,7 @@ func (b *Base) Warnf(msg string, a ...interface{}) error {
}

// Warnm is a short-hand version of Warningm
func (b *Base) Warnm(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Warnm(m *Attrs, msg string, a ...interface{}) error {
return b.Warningm(m, msg, a...)
}

Expand All @@ -319,7 316,7 @@ the resulting message to all added loggers at LogLevel.LevelWarning. It will als
merge all attributes passed in m with any attributes added to Base and include them
with the message if the Logger supports it.
*/
func (b *Base) Warningm(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Warningm(m *Attrs, msg string, a ...interface{}) error {
return b.log(LevelWarning, m, msg, a...)
}

Expand All @@ -329,7 326,7 @@ func (b *Base) Err(msg string) error {
func (b *Base) Errf(msg string, a ...interface{}) error {
return b.Errorf(msg, a...)
}
func (b *Base) Errm(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Errm(m *Attrs, msg string, a ...interface{}) error {
return b.Errorm(m, msg, a...)
}
func (b *Base) Error(msg string) error {
Expand All @@ -338,7 335,7 @@ func (b *Base) Error(msg string) error {
func (b *Base) Errorf(msg string, a ...interface{}) error {
return b.log(LevelError, nil, msg, a...)
}
func (b *Base) Errorm(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Errorm(m *Attrs, msg string, a ...interface{}) error {
return b.log(LevelError, m, msg, a...)
}

Expand All @@ -348,7 345,7 @@ func (b *Base) Fatal(msg string) error {
func (b *Base) Fatalf(msg string, a ...interface{}) error {
return b.log(LevelFatal, nil, msg, a...)
}
func (b *Base) Fatalm(m map[string]interface{}, msg string, a ...interface{}) error {
func (b *Base) Fatalm(m *Attrs, msg string, a ...interface{}) error {
return b.log(LevelFatal, m, msg, a...)
}

Expand All @@ -362,7 359,7 @@ func (b *Base) Dief(exitCode int, msg string, a ...interface{}) {
b.ShutdownLoggers()
curExiter.Exit(exitCode)
}
func (b *Base) Diem(exitCode int, m map[string]interface{}, msg string, a ...interface{}) {
func (b *Base) Diem(exitCode int, m *Attrs, msg string, a ...interface{}) {
b.log(LevelFatal, m, msg, a...)
b.ShutdownLoggers()
curExiter.Exit(exitCode)
Expand Down
103 changes: 103 additions & 0 deletions base_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 1,103 @@
package gomol

import . "gopkg.in/check.v1"

func (s *GomolSuite) BenchmarkBasicLogInsertion(c *C) {
b := NewBase()
b.SetAttr("attr1", 1234)

l := newDefaultMemLogger()
b.AddLogger(l)
b.InitLoggers()

for idx := 0; idx < c.N; idx {
b.log(
LevelDebug,
NewAttrs().
SetAttr("attr2", 4321).
SetAttr("attr3", "val3").
SetAttr("attr4", 1234),
"test %v",
1234)
}
b.ShutdownLoggers()
}

func (s *GomolSuite) BenchmarkBaseDbgm(c *C) {
b := NewBase()
b.SetAttr("attr1", 1234)

l := newDefaultMemLogger()
b.AddLogger(l)
b.InitLoggers()

for idx := 0; idx < c.N; idx {
b.Dbgm(
NewAttrs().
SetAttr("attr2", 4321).
SetAttr("attr3", "val3").
SetAttr("attr4", 1234),
"test %v",
1234)
}
b.ShutdownLoggers()
}

func (s *GomolSuite) BenchmarkLogInsertionWithFilename(c *C) {
base := NewBase()
base.config.FilenameAttr = "filename"
base.InitLoggers()
for i := 0; i < c.N; i {
base.log(LevelDebug,
NewAttrs().
SetAttr("attr1", "val1").
SetAttr("attr2", "val2").
SetAttr("attr3", 3).
SetAttr("attr4", 4),
"msg %v %v", "string", 1234)
}
base.ShutdownLoggers()
}
func (s *GomolSuite) BenchmarkLogInsertionWithLineNumber(c *C) {
base := NewBase()
base.config.LineNumberAttr = "line"
base.InitLoggers()
for i := 0; i < c.N; i {
base.log(LevelDebug,
NewAttrs().
SetAttr("attr1", "val1").
SetAttr("attr2", "val2").
SetAttr("attr3", 3).
SetAttr("attr4", 4),
"msg %v %v", "string", 1234)
}
base.ShutdownLoggers()
}
func (s *GomolSuite) BenchmarkLogInsertionWithFilenameAndLineNumber(c *C) {
base := NewBase()
base.config.FilenameAttr = "filename"
base.config.LineNumberAttr = "line"
base.InitLoggers()
for i := 0; i < c.N; i {
base.log(LevelDebug,
NewAttrs().
SetAttr("attr1", "val1").
SetAttr("attr2", "val2").
SetAttr("attr3", 3).
SetAttr("attr4", 4),
"msg %v %v", "string", 1234)
}
base.ShutdownLoggers()
}

func (s *GomolSuite) BenchmarkIsGomolCaller(c *C) {
for i := 0; i < c.N; i {
isGomolCaller("/home/gomoltest/some/sub/dir/that/is/long/filename.go")
}
}

func (s *GomolSuite) BenchmarkGetCallerInfo(c *C) {
for i := 0; i < c.N; i {
getCallerInfo()
}
}
Loading

0 comments on commit f7cb252

Please sign in to comment.