Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging interface #82

Merged
merged 3 commits into from
Feb 11, 2019
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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,31 @@ func init() {
}
```

**Logger**

xray uses an interface for its logger:

```go
type Logger interface {
Log(level LogLevel, msg fmt.Stringer)
}

const (
LogLevelDebug LogLevel = iota + 1
LogLevelInfo
LogLevelWarn
LogLevelError
)
```

The default logger logs to stdout at "info" and above. To change the logger, call `xray.SetLogger(myLogger)`. There is a default logger implementation that writes to an `io.Writer` from a specified minimum log level. For example, to log to stderr at "error" and above:

```go
xray.SetLogger(xraylog.NewDefaultLogger(os.Stderr, xraylog.LogLevelError))
yogiraj07 marked this conversation as resolved.
Show resolved Hide resolved
```

Note that the `xray.Config{}` fields `LogLevel` and `LogFormat` are deprecated and no longer have any effect.

## License

The AWS X-Ray SDK for Go is licensed under the Apache 2.0 License. See LICENSE and NOTICE.txt for more information.
6 changes: 3 additions & 3 deletions awsplugins/beanstalk/beanstalk.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"encoding/json"
"io/ioutil"

"github.com/aws/aws-xray-sdk-go/internal/logger"
yogiraj07 marked this conversation as resolved.
Show resolved Hide resolved
"github.com/aws/aws-xray-sdk-go/internal/plugins"
log "github.com/cihub/seelog"
)

const Origin = "AWS::ElasticBeanstalk::Environment"
Expand All @@ -29,14 +29,14 @@ func addPluginMetadata(pluginmd *plugins.PluginMetadata) {

rawConfig, err := ioutil.ReadFile(ebConfigPath)
if err != nil {
log.Errorf("Unable to read Elastic Beanstalk configuration file %s: %v", ebConfigPath, err)
logger.Errorf("Unable to read Elastic Beanstalk configuration file %s: %v", ebConfigPath, err)
return
}

config := &plugins.BeanstalkMetadata{}
err = json.Unmarshal(rawConfig, config)
if err != nil {
log.Errorf("Unable to unmarshal Elastic Beanstalk configuration file %s: %v", ebConfigPath, err)
logger.Errorf("Unable to unmarshal Elastic Beanstalk configuration file %s: %v", ebConfigPath, err)
return
}

Expand Down
6 changes: 3 additions & 3 deletions awsplugins/ec2/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ package ec2
import (
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-xray-sdk-go/internal/logger"
"github.com/aws/aws-xray-sdk-go/internal/plugins"
log "github.com/cihub/seelog"
)

const Origin = "AWS::EC2::Instance"
Expand All @@ -26,13 +26,13 @@ func Init() {
func addPluginMetadata(pluginmd *plugins.PluginMetadata) {
session, e := session.NewSession()
if e != nil {
log.Errorf("Unable to create a new ec2 session: %v", e)
logger.Errorf("Unable to create a new ec2 session: %v", e)
return
}
client := ec2metadata.New(session)
doc, err := client.GetInstanceIdentityDocument()
if err != nil {
log.Errorf("Unable to read EC2 instance metadata: %v", err)
logger.Errorf("Unable to read EC2 instance metadata: %v", err)
return
}

Expand Down
4 changes: 2 additions & 2 deletions awsplugins/ecs/ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ package ecs
import (
"os"

"github.com/aws/aws-xray-sdk-go/internal/logger"
"github.com/aws/aws-xray-sdk-go/internal/plugins"
log "github.com/cihub/seelog"
)

const Origin = "AWS::ECS::Container"
Expand All @@ -27,7 +27,7 @@ func addPluginMetadata(pluginmd *plugins.PluginMetadata) {
hostname, err := os.Hostname()

if err != nil {
log.Errorf("Unable to retrieve hostname from OS. %v", err)
logger.Errorf("Unable to retrieve hostname from OS. %v", err)
return
}

Expand Down
8 changes: 2 additions & 6 deletions daemoncfg/daemon_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import (
"strconv"
"strings"

log "github.com/cihub/seelog"

"github.com/aws/aws-xray-sdk-go/internal/logger"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -69,7 +68,7 @@ func GetDaemonEndpointsFromString(dAddr string) (*DaemonEndpoints, error) {
// Try to get the X-Ray daemon address from an environment variable
if envDaemonAddr := os.Getenv("AWS_XRAY_DAEMON_ADDRESS"); envDaemonAddr != "" {
daemonAddr = envDaemonAddr
log.Infof("using daemon endpoints from environment variable AWS_XRAY_DAEMON_ADDRESS: %v", envDaemonAddr)
logger.Infof("using daemon endpoints from environment variable AWS_XRAY_DAEMON_ADDRESS: %v", envDaemonAddr)
} else if dAddr != "" {
daemonAddr = dAddr
}
Expand All @@ -85,12 +84,9 @@ func resolveAddress(dAddr string) (*DaemonEndpoints, error) {
return parseSingleForm(addr[0])
} else if len(addr) == 2 {
return parseDoubleForm(addr)

} else {
return nil, errors.New("invalid daemon address: " + dAddr)
}

return nil, nil
}

func parseDoubleForm(addr []string) (*DaemonEndpoints, error) {
Expand Down
78 changes: 78 additions & 0 deletions internal/logger/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

package logger

import (
"fmt"
"os"

"github.com/aws/aws-xray-sdk-go/xraylog"
yogiraj07 marked this conversation as resolved.
Show resolved Hide resolved
)

// This internal pacakge hides the actual logging functions from the user.

// The Logger instance used by xray to log. Set via xray.SetLogger().
var Logger xraylog.Logger = xraylog.NewDefaultLogger(os.Stdout, xraylog.LogLevelInfo)

func Debugf(format string, args ...interface{}) {
Logger.Log(xraylog.LogLevelDebug, printfArgs{format, args})
}

func Debug(args ...interface{}) {
Logger.Log(xraylog.LogLevelDebug, printArgs(args))
}

func DebugDeferred(fn func() string) {
Logger.Log(xraylog.LogLevelDebug, stringerFunc(fn))
}

func Infof(format string, args ...interface{}) {
Logger.Log(xraylog.LogLevelInfo, printfArgs{format, args})
}

func Info(args ...interface{}) {
Logger.Log(xraylog.LogLevelInfo, printArgs(args))
}

func Warnf(format string, args ...interface{}) {
Logger.Log(xraylog.LogLevelWarn, printfArgs{format, args})
}

func Warn(args ...interface{}) {
Logger.Log(xraylog.LogLevelWarn, printArgs(args))
}

func Errorf(format string, args ...interface{}) {
Logger.Log(xraylog.LogLevelError, printfArgs{format, args})
}

func Error(args ...interface{}) {
Logger.Log(xraylog.LogLevelError, printArgs(args))
}

type printfArgs struct {
format string
args []interface{}
}

func (p printfArgs) String() string {
return fmt.Sprintf(p.format, p.args...)
}

type printArgs []interface{}

func (p printArgs) String() string {
return fmt.Sprint([]interface{}(p)...)
}

type stringerFunc func() string

func (sf stringerFunc) String() string {
return sf()
}
83 changes: 83 additions & 0 deletions internal/logger/logger_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

package logger

import (
"bytes"
"strings"
"testing"

"github.com/aws/aws-xray-sdk-go/xraylog"
)

func TestLogger(t *testing.T) {
oldLogger := Logger
defer func() { Logger = oldLogger }()

var buf bytes.Buffer

// filter properly by level
Logger = xraylog.NewDefaultLogger(&buf, xraylog.LogLevelWarn)

Debug("debug")
Info("info")
Warn("warn")
Error("error")

gotLines := strings.Split(strings.TrimSpace(buf.String()), "\n")
if len(gotLines) != 2 {
t.Fatalf("got %d lines", len(gotLines))
}

if !strings.Contains(gotLines[0], "[WARN] warn") {
t.Error("expected first line to be warn")
}

if !strings.Contains(gotLines[1], "[ERROR] error") {
t.Error("expected second line to be warn")
}
}

func TestDeferredDebug(t *testing.T) {
oldLogger := Logger
defer func() { Logger = oldLogger }()

var buf bytes.Buffer

Logger = xraylog.NewDefaultLogger(&buf, xraylog.LogLevelInfo)

var called bool
DebugDeferred(func() string {
called = true
return "deferred"
})

if called {
t.Error("deferred should not have been called")
}

if buf.String() != "" {
t.Errorf("unexpected log contents: %s", buf.String())
}

Logger = xraylog.NewDefaultLogger(&buf, xraylog.LogLevelDebug)

DebugDeferred(func() string {
called = true
return "deferred"
})

if !called {
t.Error("deferred should have been called")
}

if !strings.Contains(buf.String(), "[DEBUG] deferred") {
t.Errorf("expected deferred message, got %s", buf.String())
}
}
35 changes: 12 additions & 23 deletions strategy/ctxmissing/ctxmissing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,14 @@
package ctxmissing

import (
log "github.com/cihub/seelog"
"github.com/stretchr/testify/assert"
"bytes"
"strings"
"testing"
)

type LogWriter struct {
Logs []string
}

func (sw *LogWriter) Write(p []byte) (n int, err error) {
sw.Logs = append(sw.Logs, string(p))
return len(p), nil
}

func LogSetup() *LogWriter {
writer := &LogWriter{}
logger, err := log.LoggerFromWriterWithMinLevelAndFormat(writer, log.TraceLvl, "%Ns [%Level] %Msg")
if err != nil {
panic(err)
}
log.ReplaceLogger(logger)
return writer
}
"github.com/aws/aws-xray-sdk-go/internal/logger"
"github.com/aws/aws-xray-sdk-go/xraylog"
"github.com/stretchr/testify/assert"
)

func TestDefaultRuntimeErrorStrategy(t *testing.T) {
defer func() {
Expand All @@ -45,8 +29,13 @@ func TestDefaultRuntimeErrorStrategy(t *testing.T) {
}

func TestDefaultLogErrorStrategy(t *testing.T) {
logger := LogSetup()
oldLogger := logger.Logger
defer func() { logger.Logger = oldLogger }()

var buf bytes.Buffer
logger.Logger = xraylog.NewDefaultLogger(&buf, xraylog.LogLevelDebug)

l := NewDefaultLogErrorStrategy()
l.ContextMissing("TestLogError")
assert.True(t, strings.Contains(logger.Logs[0], "Suppressing AWS X-Ray context missing panic: TestLogError"))
assert.True(t, strings.Contains(buf.String(), "Suppressing AWS X-Ray context missing panic: TestLogError"))
}
6 changes: 2 additions & 4 deletions strategy/ctxmissing/default_context_missing.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@

package ctxmissing

import (
log "github.com/cihub/seelog"
)
import "github.com/aws/aws-xray-sdk-go/internal/logger"

// RuntimeErrorStrategy provides the AWS_XRAY_CONTEXT_MISSING
// environment variable value for enabling the runtime error
Expand Down Expand Up @@ -50,5 +48,5 @@ func (dr *DefaultRuntimeErrorStrategy) ContextMissing(v interface{}) {
// ContextMissing logs an error message when the
// segment context is missing.
func (dl *DefaultLogErrorStrategy) ContextMissing(v interface{}) {
log.Errorf("Suppressing AWS X-Ray context missing panic: %v", v)
logger.Errorf("Suppressing AWS X-Ray context missing panic: %v", v)
}
Loading