Skip to content

Commit

Permalink
Reorganizing files; Moving sink code to internal directory
Browse files Browse the repository at this point in the history
  • Loading branch information
Red-GV committed Apr 11, 2022
1 parent e8c5788 commit 24d9550
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 164 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/ViaQ/logerr/v2
go 1.17

require (
github.com/ViaQ/logerr v1.2.0
github.com/go-logr/logr v1.2.3
github.com/stretchr/testify v1.7.1
)
Expand Down
5 changes: 0 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
github.com/ViaQ/logerr v1.2.0 h1:thSyb8Zv7xAyWFwcxW2ppj+NK6qZ1GoNOXjDSx8zWe8=
github.com/ViaQ/logerr v1.2.0/go.mod h1:DFmaWoeJeLLixbN6yK5inb0X6meEhj7XoBp1Quoj+Wk=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2 changes: 1 addition & 1 deletion log/encoding.go → internal/sink/encoding.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package log
package sink

import (
"encoding/json"
Expand Down
78 changes: 78 additions & 0 deletions internal/sink/line.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package sink

import (
"encoding/json"
"fmt"
"strconv"
)

// Keys used to log specific builtin fields
const (
TimeStampKey = "_ts"
FileLineKey = "_file:line"
LevelKey = "_level"
ComponentKey = "_component"
MessageKey = "_message"
ErrorKey = "_error"
)

// Line orders log line fields
type Line struct {
Timestamp string
FileLine string
Verbosity string
Component string
Message string
Context map[string]interface{}
}

// LineJSON add json tags to Line struct (production logs)
type LineJSON struct {
Timestamp string `json:"_ts"`
FileLine string `json:"-"`
Verbosity string `json:"_level"`
Component string `json:"_component"`
Message string `json:"_message"`
Context map[string]interface{} `json:"-"`
}

// LineJSONDev add json tags to Line struct (developer logs, enable using environment variable LOG_DEV)
type LineJSONDev struct {
Timestamp string `json:"_ts"`
FileLine string `json:"_file:line"`
Verbosity string `json:"_level"`
Component string `json:"_component"`
Message string `json:"_message"`
Context map[string]interface{} `json:"-"`
}

// MarshalJSON implements custom marshaling for log line: (1) flattening context (2) support for developer mode
func (l Line) MarshalJSON() ([]byte, error) {
lineTemp := LineJSON(l)

lineValue, err := json.Marshal(lineTemp)
if err != nil {
return nil, err
}
verbosity, errConvert := strconv.Atoi(l.Verbosity)
if verbosity > 1 && errConvert == nil {
lineTempDev := LineJSONDev(l)
lineValue, err = json.Marshal(lineTempDev)
if err != nil {
return nil, err
}
}
lineValue = lineValue[1 : len(lineValue)-1]

contextValue, err := json.Marshal(lineTemp.Context)
if err != nil {
return nil, err
}
contextValue = contextValue[1 : len(contextValue)-1]

sep := ""
if len(contextValue) > 0 {
sep = ","
}
return []byte(fmt.Sprintf("{%s%s%s}", lineValue, sep, contextValue)), nil
}
104 changes: 2 additions & 102 deletions log/logsink.go → internal/sink/sink.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package log
package sink

import (
"encoding/json"
"fmt"
"io"
"os"
Expand All @@ -17,90 +16,6 @@ import (
"github.com/go-logr/logr"
)

// Keys used to log specific builtin fields
const (
TimeStampKey = "_ts"
FileLineKey = "_file:line"
LevelKey = "_level"
ComponentKey = "_component"
MessageKey = "_message"
ErrorKey = "_error"
)

// Line orders log line fields
type Line struct {
Timestamp string
FileLine string
Verbosity string
Component string
Message string
Context map[string]interface{}
}

// LineJSON add json tags to Line struct (production logs)
type LineJSON struct {
Timestamp string `json:"_ts"`
FileLine string `json:"-"`
Verbosity string `json:"_level"`
Component string `json:"_component"`
Message string `json:"_message"`
Context map[string]interface{} `json:"-"`
}

// LineJSONDev add json tags to Line struct (developer logs, enable using environment variable LOG_DEV)
type LineJSONDev struct {
Timestamp string `json:"_ts"`
FileLine string `json:"_file:line"`
Verbosity string `json:"_level"`
Component string `json:"_component"`
Message string `json:"_message"`
Context map[string]interface{} `json:"-"`
}

// MarshalJSON implements custom marshaling for log line: (1) flattening context (2) support for developer mode
func (l Line) MarshalJSON() ([]byte, error) {
lineTemp := LineJSON(l)

lineValue, err := json.Marshal(lineTemp)
if err != nil {
return nil, err
}
verbosity, errConvert := strconv.Atoi(l.Verbosity)
if verbosity > 1 && errConvert == nil {
lineTempDev := LineJSONDev(l)
lineValue, err = json.Marshal(lineTempDev)
if err != nil {
return nil, err
}
}
lineValue = lineValue[1 : len(lineValue)-1]

contextValue, err := json.Marshal(lineTemp.Context)
if err != nil {
return nil, err
}
contextValue = contextValue[1 : len(contextValue)-1]

sep := ""
if len(contextValue) > 0 {
sep = ","
}
return []byte(fmt.Sprintf("{%s%s%s}", lineValue, sep, contextValue)), nil
}

// Verbosity is a level of verbosity to log between 0 and math.MaxInt32
// However it is recommended to keep the numbers between 0 and 3
type Verbosity int

func (v Verbosity) String() string {
return strconv.Itoa(int(v))
}

// MarshalJSON marshas JSON
func (v Verbosity) MarshalJSON() ([]byte, error) {
return []byte(v.String()), nil
}

// TimestampFunc returns a string formatted version of the current time.
// This should probably only be used with tests or if you want to change
// the default time formatting of the output logs.
Expand Down Expand Up @@ -197,27 +112,12 @@ func (s *Sink) WithName(name string) logr.LogSink {
return NewLogSink(newName, s.output, s.verbosity, s.encoder, s.context)
}

// SetOutput sets the writer that JSON is written to
func (s *Sink) SetOutput(w io.Writer) {
s.mtx.Lock()
defer s.mtx.Unlock()

s.output = w
}

// SetVerbosity sets the log level allowed by the logsink
func (s *Sink) SetVerbosity(v int) {
s.mtx.Lock()
defer s.mtx.Unlock()

s.verbosity = Verbosity(v)
}

// log will log the message. It DOES NOT check Enabled() first so that should
// be checked by it's callers
func (s *Sink) log(msg string, context map[string]interface{}) {
_, file, line, _ := runtime.Caller(3)
file = sourcePath(file)

m := Line{
Timestamp: TimestampFunc(),
FileLine: fmt.Sprintf("%s:%s", file, strconv.Itoa(line)),
Expand Down
18 changes: 18 additions & 0 deletions internal/sink/verbosity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package sink

import (
"strconv"
)

// Verbosity is a level of verbosity to log between 0 and math.MaxInt32
// However it is recommended to keep the numbers between 0 and 3
type Verbosity int

func (v Verbosity) String() string {
return strconv.Itoa(int(v))
}

// MarshalJSON marshas JSON
func (v Verbosity) MarshalJSON() ([]byte, error) {
return []byte(v.String()), nil
}
59 changes: 19 additions & 40 deletions log/log.go
Original file line number Diff line number Diff line change
@@ -1,58 +1,37 @@
package log

import (
"fmt"
"io"
"os"

"github.com/ViaQ/logerr/v2/kverrors"
"github.com/ViaQ/logerr/v2/internal/sink"
"github.com/go-logr/logr"
)

var (
// ErrUnknownSinkType is returned when trying to perform a *Logger only function
// that is incompatible with logr.Logger interface
ErrUnknownSinkType = kverrors.New("unknown log sink type")

defaultOutput = os.Stdout

defaultLogger = logr.New(NewLogSink("", defaultOutput, 0, JSONEncoder{}))
)

// NewLogger creates a logger with the provided key value pairs
func NewLogger(component string, keyValuePairs ...interface{}) logr.Logger {
return NewLoggerWithOptions(component, nil, keyValuePairs...)
return NewLoggerWithOptions(component, Options{}, keyValuePairs...)
}

// NewLoggerWithOptions creates a logger with the provided opts and key value pairs
func NewLoggerWithOptions(component string, opts []Option, keyValuePairs ...interface{}) logr.Logger {
s := NewLogSink(component, defaultOutput, 0, JSONEncoder{}, keyValuePairs...)
func NewLoggerWithOptions(component string, opts Options, keyValuePairs ...interface{}) logr.Logger {
level := 0
var writer io.Writer = os.Stdout

for _, opt := range opts {
opt(s)
if opts.LogLevel != nil {
level = *(opts.LogLevel)
}

return logr.New(s)
}

// GetSink return the LogSink converted as a Sink object. It returns an
// error if it cannot convert it.
func GetSink(l logr.Logger) (*Sink, error) {
s, ok := l.GetSink().(*Sink)

if !ok {
return nil, kverrors.Add(ErrUnknownSinkType,
"sink_type", fmt.Sprintf("%T", s),
"expected_type", fmt.Sprintf("%T", &Sink{}),
)
if opts.Writer != nil {
writer = *(opts.Writer)
}
return s, nil
}

// MustGetSink retrieves the Sink and panics if it gets an error from GetSink
func MustGetSink(l logr.Logger) *Sink {
s, err := GetSink(l)
if err != nil {
panic(err)
}
return s
return logr.New(
sink.NewLogSink(
component,
writer,
sink.Verbosity(level),
sink.JSONEncoder{},
keyValuePairs...,
),
)
}
19 changes: 4 additions & 15 deletions log/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,8 @@ import (
"io"
)

// Option is a configuration option
type Option func(*Sink)

// WithOutput sets the output to w
func WithOutput(w io.Writer) Option {
return func(s *Sink) {
s.SetOutput(w)
}
}

// WithLogLevel sets the output log level and controls which verbosity logs are printed
func WithLogLevel(v int) Option {
return func(s *Sink) {
s.SetVerbosity(v)
}
// Options is a configuration option
type Options struct {
Writer *io.Writer
LogLevel *int
}

0 comments on commit 24d9550

Please sign in to comment.