diff --git a/commands/run.go b/commands/run.go index 3ff028d1..b716e609 100644 --- a/commands/run.go +++ b/commands/run.go @@ -67,11 +67,6 @@ func Run() { defer getAPIClient().Close() root.Execute() - - apiClient := getAPIClient() - if apiClient.HTTPLogger != nil { - apiClient.LogStats(apiClient.HTTPLogger) - } } func gitlfsCommand(cmd *cobra.Command, args []string) { @@ -129,6 +124,6 @@ func setupHTTPLogger(c *lfsapi.Client) { if err != nil { fmt.Fprintf(os.Stderr, "Error logging http stats: %s\n", err) } else { - c.HTTPLogger = file + c.LogHTTPStats(file) } } diff --git a/lfsapi/client.go b/lfsapi/client.go index 6a403fbc..4c84371a 100644 --- a/lfsapi/client.go +++ b/lfsapi/client.go @@ -78,8 +78,8 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) { } func (c *Client) Close() error { - if c.HTTPLogger != nil { - return c.HTTPLogger.Close() + if c.httpLogger != nil { + return c.httpLogger.Close() } return nil } diff --git a/lfsapi/lfsapi.go b/lfsapi/lfsapi.go index f2fd5315..bd375f8c 100644 --- a/lfsapi/lfsapi.go +++ b/lfsapi/lfsapi.go @@ -46,7 +46,7 @@ type Client struct { ntlmSessions map[string]ntlm.ClientSession ntlmMu sync.Mutex - HTTPLogger io.WriteCloser + httpLogger io.WriteCloser responses []*http.Response responseMu sync.Mutex transfers map[*http.Response]*httpTransfer diff --git a/lfsapi/stats.go b/lfsapi/stats.go index 8548db65..6117cc93 100644 --- a/lfsapi/stats.go +++ b/lfsapi/stats.go @@ -26,29 +26,17 @@ type statsContextKey string const httpStatsKey = statsContextKey("http") +func (c *Client) LogHTTPStats(w io.WriteCloser) { + fmt.Fprintf(w, "concurrent=%d time=%d version=%s\n", c.ConcurrentTransfers, time.Now().Unix(), UserAgent) + c.httpLogger = w +} + // LogStats is intended to be called after all HTTP operations for the // commmand have finished. It dumps k/v logs, one line per httpTransfer into // a log file with the current timestamp. -func (c *Client) LogStats(out io.Writer) { - if !c.LoggingStats { - return - } - - fmt.Fprintf(out, "concurrent=%d time=%d version=%s\n", c.ConcurrentTransfers, time.Now().Unix(), UserAgent) - - for _, response := range c.responses { - stats := c.transfers[response] - fmt.Fprintf(out, "key=%s reqheader=%d reqbody=%d resheader=%d resbody=%d restime=%d status=%d url=%s\n", - stats.Key, - stats.requestStats.HeaderSize, - stats.requestStats.BodySize, - stats.responseStats.HeaderSize, - stats.responseStats.BodySize, - stats.responseStats.Stop.Sub(stats.responseStats.Start).Nanoseconds(), - response.StatusCode, - response.Request.URL) - } -} +// +// DEPRECATED: Call LogHTTPStats() before the first HTTP request. +func (c *Client) LogStats(out io.Writer) {} // LogRequest tells the client to log the request's stats to the http log // after the response body has been read. @@ -90,10 +78,6 @@ func (c *Client) startResponseStats(res *http.Response, start time.Time) { t.Key = "none" } - c.responseMu.Lock() - c.responses = append(c.responses, res) - c.responseMu.Unlock() - c.transferMu.Lock() if c.transfers == nil { c.transfers = make(map[*http.Response]*httpTransfer) @@ -117,5 +101,22 @@ func (c *Client) finishResponseStats(res *http.Response, bodySize int64) { if transfer, ok := c.transfers[res]; ok { transfer.responseStats.BodySize = bodySize transfer.responseStats.Stop = time.Now() + if c.httpLogger != nil { + writeHTTPStats(c.httpLogger, res, transfer) + } + delete(c.transfers, res) } } + +func writeHTTPStats(w io.Writer, res *http.Response, t *httpTransfer) { + fmt.Fprintf(w, "key=%s reqheader=%d reqbody=%d resheader=%d resbody=%d restime=%d status=%d url=%s\n", + t.Key, + t.requestStats.HeaderSize, + t.requestStats.BodySize, + t.responseStats.HeaderSize, + t.responseStats.BodySize, + t.responseStats.Stop.Sub(t.responseStats.Start).Nanoseconds(), + res.StatusCode, + res.Request.URL, + ) +}