Browse code

[awslogs] Set User-Agent for Amazon CloudWatch Logs

Signed-off-by: Samuel Karp <skarp@amazon.com>

Samuel Karp authored on 2015/09/28 13:53:29
Showing 2 changed files
... ...
@@ -4,6 +4,7 @@ package awslogs
4 4
 import (
5 5
 	"fmt"
6 6
 	"os"
7
+	"runtime"
7 8
 	"sort"
8 9
 	"strings"
9 10
 	"sync"
... ...
@@ -13,8 +14,10 @@ import (
13 13
 	"github.com/aws/aws-sdk-go/aws"
14 14
 	"github.com/aws/aws-sdk-go/aws/awserr"
15 15
 	"github.com/aws/aws-sdk-go/aws/defaults"
16
+	"github.com/aws/aws-sdk-go/aws/request"
16 17
 	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
17 18
 	"github.com/docker/docker/daemon/logger"
19
+	"github.com/docker/docker/version"
18 20
 )
19 21
 
20 22
 const (
... ...
@@ -36,6 +39,8 @@ const (
36 36
 	resourceAlreadyExistsCode = "ResourceAlreadyExistsException"
37 37
 	dataAlreadyAcceptedCode   = "DataAlreadyAcceptedException"
38 38
 	invalidSequenceTokenCode  = "InvalidSequenceTokenException"
39
+
40
+	userAgentHeader = "User-Agent"
39 41
 )
40 42
 
41 43
 type logStream struct {
... ...
@@ -80,16 +85,10 @@ func New(ctx logger.Context) (logger.Logger, error) {
80 80
 	if ctx.Config[logStreamKey] != "" {
81 81
 		logStreamName = ctx.Config[logStreamKey]
82 82
 	}
83
-	config := defaults.DefaultConfig
84
-	if ctx.Config[regionKey] != "" {
85
-		config = defaults.DefaultConfig.Merge(&aws.Config{
86
-			Region: aws.String(ctx.Config[regionKey]),
87
-		})
88
-	}
89 83
 	containerStream := &logStream{
90 84
 		logStreamName: logStreamName,
91 85
 		logGroupName:  logGroupName,
92
-		client:        cloudwatchlogs.New(config),
86
+		client:        newAWSLogsClient(ctx),
93 87
 		messages:      make(chan *logger.Message, 4096),
94 88
 	}
95 89
 	err := containerStream.create()
... ...
@@ -101,6 +100,27 @@ func New(ctx logger.Context) (logger.Logger, error) {
101 101
 	return containerStream, nil
102 102
 }
103 103
 
104
+func newAWSLogsClient(ctx logger.Context) api {
105
+	config := defaults.DefaultConfig
106
+	if ctx.Config[regionKey] != "" {
107
+		config = defaults.DefaultConfig.Merge(&aws.Config{
108
+			Region: aws.String(ctx.Config[regionKey]),
109
+		})
110
+	}
111
+	client := cloudwatchlogs.New(config)
112
+
113
+	client.Handlers.Build.PushBackNamed(request.NamedHandler{
114
+		Name: "DockerUserAgentHandler",
115
+		Fn: func(r *request.Request) {
116
+			currentAgent := r.HTTPRequest.Header.Get(userAgentHeader)
117
+			r.HTTPRequest.Header.Set(userAgentHeader,
118
+				fmt.Sprintf("Docker %s (%s) %s",
119
+					version.VERSION, runtime.GOOS, currentAgent))
120
+		},
121
+	})
122
+	return client
123
+}
124
+
104 125
 // Name returns the name of the awslogs logging driver
105 126
 func (l *logStream) Name() string {
106 127
 	return name
... ...
@@ -2,14 +2,19 @@ package awslogs
2 2
 
3 3
 import (
4 4
 	"errors"
5
+	"fmt"
6
+	"net/http"
7
+	"runtime"
5 8
 	"strings"
6 9
 	"testing"
7 10
 	"time"
8 11
 
9 12
 	"github.com/aws/aws-sdk-go/aws"
10 13
 	"github.com/aws/aws-sdk-go/aws/awserr"
14
+	"github.com/aws/aws-sdk-go/aws/request"
11 15
 	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
12 16
 	"github.com/docker/docker/daemon/logger"
17
+	"github.com/docker/docker/version"
13 18
 )
14 19
 
15 20
 const (
... ...
@@ -20,6 +25,34 @@ const (
20 20
 	logline           = "this is a log line"
21 21
 )
22 22
 
23
+func TestNewAWSLogsClientUserAgentHandler(t *testing.T) {
24
+	ctx := logger.Context{
25
+		Config: map[string]string{
26
+			regionKey: "us-east-1",
27
+		},
28
+	}
29
+
30
+	client := newAWSLogsClient(ctx)
31
+	realClient, ok := client.(*cloudwatchlogs.CloudWatchLogs)
32
+	if !ok {
33
+		t.Fatal("Could not cast client to cloudwatchlogs.CloudWatchLogs")
34
+	}
35
+	buildHandlerList := realClient.Handlers.Build
36
+	request := &request.Request{
37
+		HTTPRequest: &http.Request{
38
+			Header: http.Header{},
39
+		},
40
+	}
41
+	buildHandlerList.Run(request)
42
+	expectedUserAgentString := fmt.Sprintf("Docker %s (%s) %s/%s",
43
+		version.VERSION, runtime.GOOS, aws.SDKName, aws.SDKVersion)
44
+	userAgent := request.HTTPRequest.Header.Get("User-Agent")
45
+	if userAgent != expectedUserAgentString {
46
+		t.Errorf("Wrong User-Agent string, expected \"%s\" but was \"%s\"",
47
+			expectedUserAgentString, userAgent)
48
+	}
49
+}
50
+
23 51
 func TestCreateSuccess(t *testing.T) {
24 52
 	mockClient := newMockClient()
25 53
 	stream := &logStream{