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

Add convenience methods Key() and Value() to log.Field #116

Merged
merged 1 commit into from
Sep 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions log/field.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package log

import "math"
import (
"fmt"
"math"
)

type fieldType int

Expand All @@ -20,7 +23,7 @@ const (
)

// Field instances are constructed via LogBool, LogString, and so on.
// Tracing implementations may then handle them via the Field.Process
// Tracing implementations may then handle them via the Field.Marshal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(thanks)

// method.
//
// "heavily influenced by" (i.e., partially stolen from)
Expand Down Expand Up @@ -198,3 +201,41 @@ func (lf Field) Marshal(visitor Encoder) {
visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger))
}
}

// Key returns the field's key.
func (lf Field) Key() string {
return lf.key
}

// Value returns the field's value as interface{}.
func (lf Field) Value() interface{} {
switch lf.fieldType {
case stringType:
return lf.stringVal
case boolType:
return lf.numericVal != 0
case intType:
return int(lf.numericVal)
case int32Type:
return int32(lf.numericVal)
case int64Type:
return int64(lf.numericVal)
case uint32Type:
return uint32(lf.numericVal)
case uint64Type:
return uint64(lf.numericVal)
case float32Type:
return math.Float32frombits(uint32(lf.numericVal))
case float64Type:
return math.Float64frombits(uint64(lf.numericVal))
case errorType, objectType, lazyLoggerType:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what we should do for lazyLoggerType... I guess this is "fine for now", though I can imagine someone expecting to see the thing the lazy log function encodes instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah.. Yeah I guess we would need to define an Encoder that captures the emitted key-value, and run the lazy logger. I'll file an issue.

BTW this makes me curious - why does the Encoder interface have an EmitLazyLogger method? Wouldn't any implementation of that (that follows the intended purpose) always just call the lazyLogger? Seems that instead of calling visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger)) we could call lf.interfaceVal.(LazyLogger)(visitor) no?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC this was adapted somewhat blindly from the zap approach... my only rationale would be that some impls might not want to do lazy logging at all, and the way things are structured now gives them more control (???). But I am just rationalizing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RaduBerinde I think the Encoder serves two purposes. At the top level it allows the implementations to be told that a log field has a lazy encoder, so the respective method is needed. But then the same interface is reused recursively in the lazy encoder signature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks. There are a few more things that could use some clarification, I filed #118 so we can move the discussion there.

return lf.interfaceVal
default:
return nil
}
}

// String returns a string representation of the key and value.
func (lf Field) String() string {
return fmt.Sprint(lf.key, ":", lf.Value())
}
35 changes: 35 additions & 0 deletions log/field_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package log

import (
"fmt"
"testing"
)

func TestFieldString(t *testing.T) {
testCases := []struct {
field Field
expected string
}{
{
field: String("key", "value"),
expected: "key:value",
},
{
field: Bool("key", true),
expected: "key:true",
},
{
field: Int("key", 5),
expected: "key:5",
},
{
field: Error(fmt.Errorf("err msg")),
expected: "error:err msg",
},
}
for i, tc := range testCases {
if str := tc.field.String(); str != tc.expected {
t.Errorf("%d: expected '%s', got '%s'", i, tc.expected, str)
}
}
}