From 480c9c01784d65a46f6ba62e8176e9b2a6a3feab Mon Sep 17 00:00:00 2001 From: Samuel Karp Date: Mon, 28 Sep 2015 04:53:29 +0000 Subject: [PATCH] [awslogs] Set User-Agent for Amazon CloudWatch Logs Signed-off-by: Samuel Karp --- daemon/logger/awslogs/cloudwatchlogs.go | 34 ++++++++++++++++---- daemon/logger/awslogs/cloudwatchlogs_test.go | 33 +++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/daemon/logger/awslogs/cloudwatchlogs.go b/daemon/logger/awslogs/cloudwatchlogs.go index b484cd2b86..55065c0f96 100644 --- a/daemon/logger/awslogs/cloudwatchlogs.go +++ b/daemon/logger/awslogs/cloudwatchlogs.go @@ -4,6 +4,7 @@ package awslogs import ( "fmt" "os" + "runtime" "sort" "strings" "sync" @@ -13,8 +14,10 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/defaults" + "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" "github.com/docker/docker/daemon/logger" + "github.com/docker/docker/version" ) const ( @@ -36,6 +39,8 @@ const ( resourceAlreadyExistsCode = "ResourceAlreadyExistsException" dataAlreadyAcceptedCode = "DataAlreadyAcceptedException" invalidSequenceTokenCode = "InvalidSequenceTokenException" + + userAgentHeader = "User-Agent" ) type logStream struct { @@ -80,16 +85,10 @@ func New(ctx logger.Context) (logger.Logger, error) { if ctx.Config[logStreamKey] != "" { logStreamName = ctx.Config[logStreamKey] } - config := defaults.DefaultConfig - if ctx.Config[regionKey] != "" { - config = defaults.DefaultConfig.Merge(&aws.Config{ - Region: aws.String(ctx.Config[regionKey]), - }) - } containerStream := &logStream{ logStreamName: logStreamName, logGroupName: logGroupName, - client: cloudwatchlogs.New(config), + client: newAWSLogsClient(ctx), messages: make(chan *logger.Message, 4096), } err := containerStream.create() @@ -101,6 +100,27 @@ func New(ctx logger.Context) (logger.Logger, error) { return containerStream, nil } +func newAWSLogsClient(ctx logger.Context) api { + config := defaults.DefaultConfig + if ctx.Config[regionKey] != "" { + config = defaults.DefaultConfig.Merge(&aws.Config{ + Region: aws.String(ctx.Config[regionKey]), + }) + } + client := cloudwatchlogs.New(config) + + client.Handlers.Build.PushBackNamed(request.NamedHandler{ + Name: "DockerUserAgentHandler", + Fn: func(r *request.Request) { + currentAgent := r.HTTPRequest.Header.Get(userAgentHeader) + r.HTTPRequest.Header.Set(userAgentHeader, + fmt.Sprintf("Docker %s (%s) %s", + version.VERSION, runtime.GOOS, currentAgent)) + }, + }) + return client +} + // Name returns the name of the awslogs logging driver func (l *logStream) Name() string { return name diff --git a/daemon/logger/awslogs/cloudwatchlogs_test.go b/daemon/logger/awslogs/cloudwatchlogs_test.go index 680cfde673..fdae93e448 100644 --- a/daemon/logger/awslogs/cloudwatchlogs_test.go +++ b/daemon/logger/awslogs/cloudwatchlogs_test.go @@ -2,14 +2,19 @@ package awslogs import ( "errors" + "fmt" + "net/http" + "runtime" "strings" "testing" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" "github.com/docker/docker/daemon/logger" + "github.com/docker/docker/version" ) const ( @@ -20,6 +25,34 @@ const ( logline = "this is a log line" ) +func TestNewAWSLogsClientUserAgentHandler(t *testing.T) { + ctx := logger.Context{ + Config: map[string]string{ + regionKey: "us-east-1", + }, + } + + client := newAWSLogsClient(ctx) + realClient, ok := client.(*cloudwatchlogs.CloudWatchLogs) + if !ok { + t.Fatal("Could not cast client to cloudwatchlogs.CloudWatchLogs") + } + buildHandlerList := realClient.Handlers.Build + request := &request.Request{ + HTTPRequest: &http.Request{ + Header: http.Header{}, + }, + } + buildHandlerList.Run(request) + expectedUserAgentString := fmt.Sprintf("Docker %s (%s) %s/%s", + version.VERSION, runtime.GOOS, aws.SDKName, aws.SDKVersion) + userAgent := request.HTTPRequest.Header.Get("User-Agent") + if userAgent != expectedUserAgentString { + t.Errorf("Wrong User-Agent string, expected \"%s\" but was \"%s\"", + expectedUserAgentString, userAgent) + } +} + func TestCreateSuccess(t *testing.T) { mockClient := newMockClient() stream := &logStream{