Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2021-06-18 12:04:16 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2021-06-30 13:03:43 +0300
commit75ccb2ef11efbf803c8b4b9fb457dfb5ea78eb32 (patch)
tree119470ef9dd2ab2aed62ad7b9250d55baf84e9ff
parent5694344d3ee87c4f6ab663197596ba860f63ef50 (diff)
stats: Split up HTTP stats code
Split up the code which handles generation of HTTP stats into multiple files and prefix relevant public structures with `HTTP` to make their scope clear. This is in preparation for a new probe type for pushes, which will add additional HTTP logic.
-rw-r--r--cmd/gitaly-debug/analyzehttp.go2
-rw-r--r--internal/blackbox/blackbox.go2
-rw-r--r--internal/git/stats/http_clone.go49
-rw-r--r--internal/git/stats/http_clone_test.go (renamed from internal/git/stats/clone_test.go)4
-rw-r--r--internal/git/stats/http_fetch_pack.go (renamed from internal/git/stats/clone.go)147
-rw-r--r--internal/git/stats/http_reference_discovery.go113
6 files changed, 166 insertions, 151 deletions
diff --git a/cmd/gitaly-debug/analyzehttp.go b/cmd/gitaly-debug/analyzehttp.go
index dda0cb11e..805094ac7 100644
--- a/cmd/gitaly-debug/analyzehttp.go
+++ b/cmd/gitaly-debug/analyzehttp.go
@@ -8,7 +8,7 @@ import (
)
func analyzeHTTPClone(cloneURL string) {
- st, err := stats.PerformClone(context.Background(), cloneURL, "", "", true)
+ st, err := stats.PerformHTTPClone(context.Background(), cloneURL, "", "", true)
noError(err)
fmt.Println("\n--- Reference discovery metrics:")
diff --git a/internal/blackbox/blackbox.go b/internal/blackbox/blackbox.go
index dd77d60f8..bffcca8b2 100644
--- a/internal/blackbox/blackbox.go
+++ b/internal/blackbox/blackbox.go
@@ -105,7 +105,7 @@ func (b Blackbox) doProbe(probe Probe) {
entry := log.WithField("probe", probe.Name)
entry.Info("starting probe")
- clone, err := stats.PerformClone(ctx, probe.URL, probe.User, probe.Password, false)
+ clone, err := stats.PerformHTTPClone(ctx, probe.URL, probe.User, probe.Password, false)
if err != nil {
entry.WithError(err).Error("probe failed")
return
diff --git a/internal/git/stats/http_clone.go b/internal/git/stats/http_clone.go
new file mode 100644
index 000000000..e47ecf06d
--- /dev/null
+++ b/internal/git/stats/http_clone.go
@@ -0,0 +1,49 @@
+package stats
+
+import (
+ "context"
+ "fmt"
+)
+
+// HTTPClone hosts information about a typical HTTP-based clone.
+type HTTPClone struct {
+ // ReferenceDiscovery is the reference discovery performed as part of the clone.
+ ReferenceDiscovery HTTPReferenceDiscovery
+ // FetchPack is the response to a git-fetch-pack(1) request which computes and transmits the
+ // packfile.
+ FetchPack HTTPFetchPack
+}
+
+// PerformHTTPClone does a Git HTTP clone, discarding cloned data to /dev/null.
+func PerformHTTPClone(ctx context.Context, url, user, password string, interactive bool) (HTTPClone, error) {
+ printInteractive := func(format string, a ...interface{}) {
+ if interactive {
+ // Ignore any errors returned by this given that we only use it as a
+ // debugging aid to write to stdout.
+ fmt.Printf(format, a...)
+ }
+ }
+
+ referenceDiscovery, err := performHTTPReferenceDiscovery(ctx, url, user, password, printInteractive)
+ if err != nil {
+ return HTTPClone{}, ctxErr(ctx, err)
+ }
+
+ fetchPack, err := performFetchPack(ctx, url, user, password,
+ referenceDiscovery.Refs(), printInteractive)
+ if err != nil {
+ return HTTPClone{}, ctxErr(ctx, err)
+ }
+
+ return HTTPClone{
+ ReferenceDiscovery: referenceDiscovery,
+ FetchPack: fetchPack,
+ }, nil
+}
+
+func ctxErr(ctx context.Context, err error) error {
+ if ctx.Err() != nil {
+ return ctx.Err()
+ }
+ return err
+}
diff --git a/internal/git/stats/clone_test.go b/internal/git/stats/http_clone_test.go
index 4e25cea93..1c287fa50 100644
--- a/internal/git/stats/clone_test.go
+++ b/internal/git/stats/http_clone_test.go
@@ -24,7 +24,7 @@ func TestClone(t *testing.T) {
require.NoError(t, stopGitServer())
}()
- clone, err := PerformClone(ctx, fmt.Sprintf("http://localhost:%d/%s", serverPort, filepath.Base(repoPath)), "", "", false)
+ clone, err := PerformHTTPClone(ctx, fmt.Sprintf("http://localhost:%d/%s", serverPort, filepath.Base(repoPath)), "", "", false)
require.NoError(t, err, "perform analysis clone")
const expectedRequests = 90 // based on contents of _support/gitlab-test.git-packed-refs
@@ -100,7 +100,7 @@ func TestCloneWithAuth(t *testing.T) {
require.NoError(t, stopGitServer())
}()
- _, err := PerformClone(
+ _, err := PerformHTTPClone(
ctx,
fmt.Sprintf("http://localhost:%d/%s", serverPort, filepath.Base(repoPath)),
user,
diff --git a/internal/git/stats/clone.go b/internal/git/stats/http_fetch_pack.go
index 18f881e9a..a688e7c19 100644
--- a/internal/git/stats/clone.go
+++ b/internal/git/stats/http_fetch_pack.go
@@ -5,8 +5,6 @@ import (
"compress/gzip"
"context"
"fmt"
- "io"
- "io/ioutil"
"net/http"
"strings"
"time"
@@ -14,151 +12,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v14/internal/git/pktline"
)
-// Clone hosts information about a typical HTTP-based clone.
-type Clone struct {
- // ReferenceDiscovery is the reference discovery performed as part of the clone.
- ReferenceDiscovery HTTPReferenceDiscovery
- // FetchPack is the response to a git-fetch-pack(1) request which computes transmits the
- // packfile.
- FetchPack HTTPFetchPack
-}
-
-// PerformClone does a Git HTTP clone, discarding cloned data to /dev/null.
-func PerformClone(ctx context.Context, url, user, password string, interactive bool) (Clone, error) {
- printInteractive := func(format string, a ...interface{}) {
- if interactive {
- // Ignore any errors returned by this given that we only use it as a
- // debugging aid to write to stdout.
- fmt.Printf(format, a...)
- }
- }
-
- referenceDiscovery, err := performReferenceDiscovery(ctx, url, user, password, printInteractive)
- if err != nil {
- return Clone{}, ctxErr(ctx, err)
- }
-
- fetchPack, err := performFetchPack(ctx, url, user, password,
- referenceDiscovery.Refs(), printInteractive)
- if err != nil {
- return Clone{}, ctxErr(ctx, err)
- }
-
- return Clone{
- ReferenceDiscovery: referenceDiscovery,
- FetchPack: fetchPack,
- }, nil
-}
-
-func ctxErr(ctx context.Context, err error) error {
- if ctx.Err() != nil {
- return ctx.Err()
- }
- return err
-}
-
-// HTTPReferenceDiscovery is a ReferenceDiscovery obtained via a clone of a target repository via
-// HTTP. It contains additional information about the cloning process like status codes and
-// timings.
-type HTTPReferenceDiscovery struct {
- start time.Time
- responseHeader time.Duration
- httpStatus int
- stats ReferenceDiscovery
-}
-
-// ResponseHeader returns how long it took to receive the response header.
-func (d HTTPReferenceDiscovery) ResponseHeader() time.Duration { return d.responseHeader }
-
-// HTTPStatus returns the HTTP status code.
-func (d HTTPReferenceDiscovery) HTTPStatus() int { return d.httpStatus }
-
-// FirstGitPacket returns how long it took to receive the first Git packet.
-func (d HTTPReferenceDiscovery) FirstGitPacket() time.Duration {
- return d.stats.FirstPacket.Sub(d.start)
-}
-
-// ResponseBody returns how long it took to receive the first bytes of the response body.
-func (d HTTPReferenceDiscovery) ResponseBody() time.Duration {
- return d.stats.LastPacket.Sub(d.start)
-}
-
-// Refs returns all announced references.
-func (d HTTPReferenceDiscovery) Refs() []Reference { return d.stats.Refs }
-
-// Packets returns the number of Git packets received.
-func (d HTTPReferenceDiscovery) Packets() int { return d.stats.Packets }
-
-// PayloadSize returns the total size of all pktlines' data.
-func (d HTTPReferenceDiscovery) PayloadSize() int64 { return d.stats.PayloadSize }
-
-// Caps returns all announced capabilities.
-func (d HTTPReferenceDiscovery) Caps() []string { return d.stats.Caps }
-
-func performReferenceDiscovery(
- ctx context.Context,
- url, user, password string,
- reportProgress func(string, ...interface{}),
-) (HTTPReferenceDiscovery, error) {
- var referenceDiscovery HTTPReferenceDiscovery
-
- req, err := http.NewRequest("GET", url+"/info/refs?service=git-upload-pack", nil)
- if err != nil {
- return HTTPReferenceDiscovery{}, err
- }
-
- req = req.WithContext(ctx)
- if user != "" {
- req.SetBasicAuth(user, password)
- }
-
- for k, v := range map[string]string{
- "User-Agent": "gitaly-debug",
- "Accept": "*/*",
- "Accept-Encoding": "deflate, gzip",
- "Pragma": "no-cache",
- } {
- req.Header.Set(k, v)
- }
-
- referenceDiscovery.start = time.Now()
- reportProgress("---\n")
- reportProgress("--- GET %v\n", req.URL)
- reportProgress("---\n")
-
- resp, err := http.DefaultClient.Do(req)
- if err != nil {
- return HTTPReferenceDiscovery{}, err
- }
- defer func() {
- io.Copy(ioutil.Discard, resp.Body)
- resp.Body.Close()
- }()
-
- if code := resp.StatusCode; code < 200 || code >= 400 {
- return HTTPReferenceDiscovery{}, fmt.Errorf("git http get: unexpected http status: %d", code)
- }
-
- referenceDiscovery.responseHeader = time.Since(referenceDiscovery.start)
- referenceDiscovery.httpStatus = resp.StatusCode
- reportProgress("response code: %d\n", resp.StatusCode)
- reportProgress("response header: %v\n", resp.Header)
-
- body := resp.Body
- if resp.Header.Get("Content-Encoding") == "gzip" {
- body, err = gzip.NewReader(body)
- if err != nil {
- return HTTPReferenceDiscovery{}, err
- }
- }
-
- if err := referenceDiscovery.stats.Parse(body); err != nil {
- return HTTPReferenceDiscovery{}, err
- }
-
- return referenceDiscovery, nil
-}
-
// HTTPFetchPack is a FetchPack obtained via a clone of a target repository via HTTP. It contains
// additional information about the cloning process like status codes and timings.
type HTTPFetchPack struct {
diff --git a/internal/git/stats/http_reference_discovery.go b/internal/git/stats/http_reference_discovery.go
new file mode 100644
index 000000000..7792f49f3
--- /dev/null
+++ b/internal/git/stats/http_reference_discovery.go
@@ -0,0 +1,113 @@
+package stats
+
+import (
+ "compress/gzip"
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "time"
+)
+
+// HTTPReferenceDiscovery is a ReferenceDiscovery obtained via a clone of a target repository via
+// HTTP. It contains additional information about the cloning process like status codes and
+// timings.
+type HTTPReferenceDiscovery struct {
+ start time.Time
+ responseHeader time.Duration
+ httpStatus int
+ stats ReferenceDiscovery
+}
+
+// ResponseHeader returns how long it took to receive the response header.
+func (d HTTPReferenceDiscovery) ResponseHeader() time.Duration { return d.responseHeader }
+
+// HTTPStatus returns the HTTP status code.
+func (d HTTPReferenceDiscovery) HTTPStatus() int { return d.httpStatus }
+
+// FirstGitPacket returns how long it took to receive the first Git packet.
+func (d HTTPReferenceDiscovery) FirstGitPacket() time.Duration {
+ return d.stats.FirstPacket.Sub(d.start)
+}
+
+// ResponseBody returns how long it took to receive the first bytes of the response body.
+func (d HTTPReferenceDiscovery) ResponseBody() time.Duration {
+ return d.stats.LastPacket.Sub(d.start)
+}
+
+// Refs returns all announced references.
+func (d HTTPReferenceDiscovery) Refs() []Reference { return d.stats.Refs }
+
+// Packets returns the number of Git packets received.
+func (d HTTPReferenceDiscovery) Packets() int { return d.stats.Packets }
+
+// PayloadSize returns the total size of all pktlines' data.
+func (d HTTPReferenceDiscovery) PayloadSize() int64 { return d.stats.PayloadSize }
+
+// Caps returns all announced capabilities.
+func (d HTTPReferenceDiscovery) Caps() []string { return d.stats.Caps }
+
+func performHTTPReferenceDiscovery(
+ ctx context.Context,
+ url, user, password string,
+ reportProgress func(string, ...interface{}),
+) (HTTPReferenceDiscovery, error) {
+ var referenceDiscovery HTTPReferenceDiscovery
+
+ req, err := http.NewRequest("GET", url+"/info/refs?service=git-upload-pack", nil)
+ if err != nil {
+ return HTTPReferenceDiscovery{}, err
+ }
+
+ req = req.WithContext(ctx)
+ if user != "" {
+ req.SetBasicAuth(user, password)
+ }
+
+ for k, v := range map[string]string{
+ "User-Agent": "gitaly-debug",
+ "Accept": "*/*",
+ "Accept-Encoding": "deflate, gzip",
+ "Pragma": "no-cache",
+ } {
+ req.Header.Set(k, v)
+ }
+
+ referenceDiscovery.start = time.Now()
+ reportProgress("---\n")
+ reportProgress("--- GET %v\n", req.URL)
+ reportProgress("---\n")
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return HTTPReferenceDiscovery{}, err
+ }
+ defer func() {
+ io.Copy(ioutil.Discard, resp.Body)
+ resp.Body.Close()
+ }()
+
+ if code := resp.StatusCode; code < 200 || code >= 400 {
+ return HTTPReferenceDiscovery{}, fmt.Errorf("git http get: unexpected http status: %d", code)
+ }
+
+ referenceDiscovery.responseHeader = time.Since(referenceDiscovery.start)
+ referenceDiscovery.httpStatus = resp.StatusCode
+ reportProgress("response code: %d\n", resp.StatusCode)
+ reportProgress("response header: %v\n", resp.Header)
+
+ body := resp.Body
+ if resp.Header.Get("Content-Encoding") == "gzip" {
+ body, err = gzip.NewReader(body)
+ if err != nil {
+ return HTTPReferenceDiscovery{}, err
+ }
+ }
+
+ if err := referenceDiscovery.stats.Parse(body); err != nil {
+ return HTTPReferenceDiscovery{}, err
+ }
+
+ return referenceDiscovery, nil
+}