Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mdeltito committed Oct 1, 2020
1 parent 9e98963 commit 43cd578
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 69 deletions.
29 changes: 18 additions & 11 deletions logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package logger

import (
"encoding/json"
"time"

"github.com/joho/godotenv"
)
Expand All @@ -15,8 +16,9 @@ type Logger struct {

// Message represents a single log message and associated options.
type Message struct {
Body string
Options Options
Body string
Options MessageOptions
Timestamp time.Time
}

// Payload contains the properties sent to the ingestion endpoint.
Expand Down Expand Up @@ -71,7 +73,7 @@ func NewLogger(options Options, key string) (*Logger, error) {
options.setDefaults()
logger := Logger{
Options: options,
transport: newTransport(options, key),
transport: newTransport(&options, key),
}

return &logger, nil
Expand All @@ -85,24 +87,29 @@ func (l *Logger) Close() {
// Log sends a provided log message to LogDNA.
func (l *Logger) Log(message string) {
logMsg := Message{
Body: message,
Options: l.Options,
Body: message,
Timestamp: time.Now(),
}
l.transport.add(logMsg)
}

// LogWithOptions allows the user to update options uniquely for a given log message
// before sending the log to LogDNA.
func (l *Logger) LogWithOptions(message string, options Options) error {
msgOpts := l.Options.merge(options)
err := msgOpts.validate()
func (l *Logger) LogWithOptions(message string, options MessageOptions) error {
err := options.validate()
if err != nil {
return err
}

timestamp := options.Timestamp
if timestamp.IsZero() {
timestamp = time.Now()
}

logMsg := Message{
Body: message,
Options: msgOpts,
Body: message,
Options: options,
Timestamp: timestamp,
}

l.transport.add(logMsg)
Expand All @@ -111,7 +118,7 @@ func (l *Logger) LogWithOptions(message string, options Options) error {

// LogWithLevel sends a log message to LogDNA with a parameterized level.
func (l *Logger) LogWithLevel(message string, level string) error {
options := Options{Level: level}
options := MessageOptions{Level: level}
return l.LogWithOptions(message, options)
}

Expand Down
12 changes: 6 additions & 6 deletions logger/logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,16 @@ func TestLogger_LogWithOptions(t *testing.T) {
App: "app",
Env: "development",
Level: "info",
Timestamp: now,
}

l, err := NewLogger(o, "abc123")
assert.Equal(t, nil, err)

l.LogWithOptions("testing", Options{
App: "anotherapp",
Env: "production",
Level: "error",
l.LogWithOptions("testing", MessageOptions{
App: "anotherapp",
Env: "production",
Level: "error",
Timestamp: now,
})
l.Close()

Expand All @@ -139,7 +139,7 @@ func TestLogger_LogWithOptions(t *testing.T) {
l, err := NewLogger(o, "abc123")
assert.Equal(t, nil, err)

err = l.LogWithOptions("testing", Options{
err = l.LogWithOptions("testing", MessageOptions{
App: strings.Repeat("a", 83),
})

Expand Down
47 changes: 29 additions & 18 deletions logger/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,40 @@ const (
maxOptionLength = 80
)

var reHostname = regexp.MustCompile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$`)

// InvalidOptionMessage represents an issue with the supplied configuration.
type InvalidOptionMessage struct {
Option string
Message string
}

// Options encapsulates user-provided options such as the Level and App
// that are passed along with each log.
// Options encapsulates the Logger-level options as well as default
// values for messages logged through a Logger instance.
type Options struct {
App string
Env string
Level string
Meta string
FlushInterval time.Duration
SendTimeout time.Duration
Hostname string
IndexMeta bool
IngestURL string
IPAddress string
Level string
MacAddress string
MaxBufferLen int
Meta string
Tags string
Timestamp time.Time
}

// MessageOptions defines Message-specific options for overriding
// values from the Logger instance.
type MessageOptions struct {
App string
Env string
Level string
Meta string
Timestamp time.Time
}

type fieldIssue struct {
Expand Down Expand Up @@ -67,7 +78,6 @@ func validateOptionLength(option string, value string) *fieldIssue {
}

func (options *Options) validate() error {
reHostname := regexp.MustCompile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$`)
var issues []fieldIssue

if issue := validateOptionLength("App", options.App); issue != nil {
Expand Down Expand Up @@ -104,22 +114,23 @@ func (options *Options) validate() error {
return nil
}

func (options Options) merge(merge Options) Options {
newOpts := options
if merge.App != "" {
newOpts.App = merge.App
}
if merge.Env != "" {
newOpts.Env = merge.Env
func (options *MessageOptions) validate() error {
var issues []fieldIssue

if issue := validateOptionLength("App", options.App); issue != nil {
issues = append(issues, *issue)
}
if merge.Level != "" {
newOpts.Level = merge.Level
if issue := validateOptionLength("Env", options.Env); issue != nil {
issues = append(issues, *issue)
}
if merge.Meta != "" {
newOpts.Meta = merge.Meta
if issue := validateOptionLength("Level", options.Level); issue != nil {
issues = append(issues, *issue)
}

return newOpts
if len(issues) > 0 {
return &optionsError{issues: issues}
}
return nil
}

func (options *Options) setDefaults() {
Expand Down
21 changes: 0 additions & 21 deletions logger/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,6 @@ func TestOptions_Validate(t *testing.T) {
}
}

func TestOptions_Merge(t *testing.T) {
o := Options{
App: "app",
Env: "development",
Level: "info",
Meta: `{"foo": "bar"}`,
}

o = o.merge(Options{
App: "merge",
Env: "merge",
Level: "merge",
Meta: `{"baz": "merge"}`,
})

assert.Equal(t, "merge", o.App)
assert.Equal(t, "merge", o.Env)
assert.Equal(t, "merge", o.Level)
assert.Equal(t, `{"baz": "merge"}`, o.Meta)
}

func TestOptions_SetDefaults(t *testing.T) {
t.Run("Sets defaults", func(t *testing.T) {
o := Options{}
Expand Down
49 changes: 36 additions & 13 deletions logger/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import (
type transport struct {
key string
buffer []Message
options Options
options *Options
done chan struct{}

mu sync.Mutex
wg sync.WaitGroup
}

func newTransport(options Options, key string) *transport {
func newTransport(options *Options, key string) *transport {
t := transport{
key: key,
options: options,
Expand Down Expand Up @@ -91,23 +91,46 @@ func (t *transport) flushSend() {
func (t *transport) send(msgs []Message) error {
var lines []Line
for _, msg := range msgs {
line := Line{
Body: msg.Body,
App: msg.Options.App,
Env: msg.Options.Env,
Level: msg.Options.Level,
var app string
if msg.Options.App != "" {
app = msg.Options.App
} else {
app = t.options.App
}

var env string
if msg.Options.Env != "" {
env = msg.Options.Env
} else {
env = t.options.Env
}

timestamp := msg.Options.Timestamp
if timestamp.IsZero() {
timestamp = time.Now()
var level string
if msg.Options.Level != "" {
level = msg.Options.Level
} else {
level = t.options.Level
}
line.Timestamp = timestamp.UnixNano() / int64(time.Millisecond)

var meta string
if msg.Options.Meta != "" {
meta = msg.Options.Meta
} else {
meta = t.options.Meta
}

line := Line{
Body: msg.Body,
Timestamp: msg.Timestamp.UnixNano() / int64(time.Millisecond),
App: app,
Env: env,
Level: level,
}

if meta != "" {
line.Meta = metaEnvelope{
indexed: msg.Options.IndexMeta,
meta: msg.Options.Meta,
indexed: t.options.IndexMeta,
meta: meta,
}
}

Expand Down

0 comments on commit 43cd578

Please sign in to comment.