Repository: open-telemetry/opamp-go (go)

Issue:
Allow the agent User-Agent header to be configurable
I would like to be able to control the User-Agent header of the agent when communicating with the management server. Currently this defaults to `Go-http-client/1.1`. It can be useful to identify traffic for logging.

I would propose adding a `UserAgent string` field to `StartSettings` and setting the User-Agent header when we set the Authorization header.

Pull request:
Add Header and remove AuthorizationHeader to allow any HTTP header to be specified
Resolves #79 

Patch:
diff --git a/client/httpclient.go b/client/httpclient.go
index f624337..b32f691 100644
--- a/client/httpclient.go
+++ b/client/httpclient.go
@@ -41,9 +41,7 @@ func (c *httpClient) Start(ctx context.Context, settings types.StartSettings) er
 	c.opAMPServerURL = settings.OpAMPServerURL
 
 	// Prepare Server connection settings.
-	if settings.AuthorizationHeader != "" {
-		c.sender.SetRequestHeader("Authorization", settings.AuthorizationHeader)
-	}
+	c.sender.SetRequestHeader(settings.Header)
 
 	// Prepare the first message to send.
 	err := c.common.PrepareFirstMessage(ctx)
diff --git a/client/internal/httpsender.go b/client/internal/httpsender.go
index ed1018f..ec4ad68 100644
--- a/client/internal/httpsender.go
+++ b/client/internal/httpsender.go
@@ -46,10 +46,10 @@ func NewHTTPSender(logger types.Logger) *HTTPSender {
 		SenderCommon:      NewSenderCommon(),
 		logger:            logger,
 		client:            http.DefaultClient,
-		requestHeader:     http.Header{},
 		pollingIntervalMs: defaultPollingIntervalMs,
 	}
-	h.requestHeader.Set(headerContentType, contentTypeProtobuf)
+	// initialize the headers with no additional headers
+	h.SetRequestHeader(nil)
 	return h
 }
 
@@ -86,10 +86,14 @@ func (h *HTTPSender) Run(ctx context.Context, url string, callbacks types.Callba
 	}
 }
 
-// SetRequestHeader sets an additional HTTP header to send with all future requests.
+// SetRequestHeader sets additional HTTP headers to send with all future requests.
 // Should not be called concurrently with any other method.
-func (h *HTTPSender) SetRequestHeader(key, value string) {
-	h.requestHeader.Set(key, value)
+func (h *HTTPSender) SetRequestHeader(header http.Header) {
+	if header == nil {
+		header = http.Header{}
+	}
+	h.requestHeader = header
+	h.requestHeader.Set(headerContentType, contentTypeProtobuf)
 }
 
 func (h *HTTPSender) makeOneRequestRoundtrip(ctx context.Context) {
diff --git a/client/types/startsettings.go b/client/types/startsettings.go
index f2fe95c..870a9b1 100644
--- a/client/types/startsettings.go
+++ b/client/types/startsettings.go
@@ -2,6 +2,7 @@ package types
 
 import (
 	"crypto/tls"
+	"net/http"
 
 	"github.com/open-telemetry/opamp-go/protobufs"
 )
@@ -12,8 +13,8 @@ type StartSettings struct {
 	// Server URL. MUST be set.
 	OpAMPServerURL string
 
-	// Optional value of "Authorization" HTTP header in the HTTP request.
-	AuthorizationHeader string
+	// Optional additional HTTP headers to send with all HTTP requests.
+	Header http.Header
 
 	// Optional TLS config for HTTP connection.
 	TLSConfig *tls.Config
diff --git a/client/wsclient.go b/client/wsclient.go
index 0933c9a..aa3e424 100644
--- a/client/wsclient.go
+++ b/client/wsclient.go
@@ -69,10 +69,7 @@ func (c *wsClient) Start(ctx context.Context, settings types.StartSettings) erro
 	}
 	c.dialer.TLSClientConfig = settings.TLSConfig
 
-	if settings.AuthorizationHeader != "" {
-		c.requestHeader = http.Header{}
-		c.requestHeader["Authorization"] = []string{settings.AuthorizationHeader}
-	}
+	c.requestHeader = settings.Header
 
 	c.common.StartConnectAndRun(c.runUntilStopped)
 


Test patch:
diff --git a/client/clientimpl_test.go b/client/clientimpl_test.go
index 837d710..03db4d1 100644
--- a/client/clientimpl_test.go
+++ b/client/clientimpl_test.go
@@ -269,13 +269,19 @@ func TestConnectWithHeader(t *testing.T) {
 		srv.OnConnect = func(r *http.Request) {
 			authHdr := r.Header.Get("Authorization")
 			assert.EqualValues(t, "Bearer 12345678", authHdr)
+			userAgentHdr := r.Header.Get("User-Agent")
+			assert.EqualValues(t, "custom-agent/1.0", userAgentHdr)
 			conn.Store(true)
 		}
 
+		header := http.Header{}
+		header.Set("Authorization", "Bearer 12345678")
+		header.Set("User-Agent", "custom-agent/1.0")
+
 		// Start a client.
 		settings := types.StartSettings{
-			OpAMPServerURL:      "ws://" + srv.Endpoint,
-			AuthorizationHeader: "Bearer 12345678",
+			OpAMPServerURL: "ws://" + srv.Endpoint,
+			Header:         header,
 		}
 		startClient(t, settings, client)