diff --git a/glustercli/cmd/common.go b/glustercli/cmd/common.go index bc6471ab3..cc51f8c8d 100644 --- a/glustercli/cmd/common.go +++ b/glustercli/cmd/common.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/gluster/glusterd2/pkg/restclient" + "github.com/gluster/glusterd2/version" ) var ( @@ -20,6 +21,8 @@ var ( func initRESTClient(hostname, user, secret, cacert string, insecure bool) { client = restclient.New(hostname, user, secret, cacert, insecure) + client.ExtendAgent( + fmt.Sprintf("glustercli/%v", version.GlusterdVersion)) } func isConnectionRefusedErr(err error) bool { diff --git a/glustercli/cmd/root.go b/glustercli/cmd/root.go index a6fef09aa..6ac4f6634 100644 --- a/glustercli/cmd/root.go +++ b/glustercli/cmd/root.go @@ -47,6 +47,10 @@ var RootCmd = &cobra.Command{ } initRESTClient(flagEndpoints[0], flagUser, secret, flagCacert, flagInsecure) + if len(os.Args) > 1 { + args := []string{"glustercli"} + client.SetOriginArgs(append(args, os.Args[1:]...)) + } }, } diff --git a/glusterd2/middleware/request_logging.go b/glusterd2/middleware/request_logging.go index cc314d2d7..9890e10bc 100644 --- a/glusterd2/middleware/request_logging.go +++ b/glusterd2/middleware/request_logging.go @@ -14,8 +14,20 @@ import ( // Apache Common Log Format (CLF) func LogRequest(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - entry := log.WithField("reqid", gdctx.GetReqID(r.Context()).String()) + f := log.Fields{ + "subsys": "rest", + "reqid": gdctx.GetReqID(r.Context()).String(), + } + if origin := r.Header.Get("X-Gluster-Origin-Args"); origin != "" { + f["origin"] = origin + } + entry := log.WithFields(f) + entry.WithFields(log.Fields{ + "method": r.Method, + "url": r.URL, + "client": r.UserAgent(), + }).Info("HTTP Request") delete(entry.Data, logging.SourceField) - handlers.LoggingHandler(entry.Writer(), next).ServeHTTP(w, r) + handlers.CombinedLoggingHandler(entry.Writer(), next).ServeHTTP(w, r) }) } diff --git a/pkg/restclient/common.go b/pkg/restclient/common.go index 02a421c9e..eeaac77b6 100644 --- a/pkg/restclient/common.go +++ b/pkg/restclient/common.go @@ -13,6 +13,7 @@ import ( "time" "github.com/gluster/glusterd2/pkg/api" + "github.com/gluster/glusterd2/version" "github.com/dgrijalva/jwt-go" ) @@ -29,11 +30,18 @@ type Client struct { password string cacert string insecure bool + + // Add to the identifier to further specify the client + // using the api. + agent string + originArgs []string } // New creates new instance of Glusterd REST Client func New(baseURL string, username string, password string, cacert string, insecure bool) *Client { - return &Client{baseURL, username, password, cacert, insecure} + return &Client{baseURL, username, password, cacert, insecure, + fmt.Sprintf("GlusterD2-rest-client/%v", version.GlusterdVersion), + []string{}} } func parseHTTPError(jsonData []byte) string { @@ -105,6 +113,7 @@ func (c *Client) do(method string, url string, data interface{}, expectStatusCod if err != nil { return err } + c.setAgent(req) req.Header.Set("Accept", "application/json") req.Header.Set("Content-Type", "application/json") req.Close = true @@ -114,6 +123,8 @@ func (c *Client) do(method string, url string, data interface{}, expectStatusCod req.Header.Set("Authorization", "bearer "+getAuthToken(c.username, c.password)) } + c.sendOriginArgs(req) + tr := &http.Transport{ DisableCompression: true, DisableKeepAlives: true, @@ -163,3 +174,34 @@ func (c *Client) do(method string, url string, data interface{}, expectStatusCod func (c *Client) Ping() error { return c.get("/ping", nil, http.StatusOK, nil) } + +func (c *Client) setAgent(req *http.Request) { + req.Header.Set("User-Agent", + fmt.Sprintf("%v (Go-http-client/1.1)", c.agent)) +} + +// ExtendAgent adds the given string to the client's user agent +// by prefixing it to the existing agent information. +// This allows client programs to identify themselves more than +// just something using the rest client api. +func (c *Client) ExtendAgent(a string) { + // new additions to the agent identifier go to the + // beginning of the string. It is meant to read like: + // foo (based on) bar (based on) baz, etc... + c.agent = fmt.Sprintf("%v %v", a, c.agent) +} + +func (c *Client) sendOriginArgs(req *http.Request) { + if len(c.originArgs) != 0 { + req.Header.Set("X-Gluster-Origin-Args", + fmt.Sprintf("1:%#v", strings.Join(c.originArgs, " "))) + } +} + +// SetOriginArgs provides a way for tools using this library to +// inform the server what arguments were provided to generate +// the api call(s). The contents of the array are meant only for +// human interpretation but will generally be command line args. +func (c *Client) SetOriginArgs(a []string) { + c.originArgs = a +}