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>2020-03-27 15:19:37 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2020-03-27 15:19:37 +0300
commit8479700f188ecbbf282a7ef73b709d79bb2ef66d (patch)
tree92e21ec07aa47655d8a1ee15d87d156916c8fe84
parent59d0b87438608e2d41399421b74563ab93b9db1f (diff)
parent6ba915feea373d98aa4f337773f94921c65d239f (diff)
Merge branch 'pks-upload-pack-prometheus' into 'master'
Expose Prometheus metrics for shallow, partial and initial clones See merge request gitlab-org/gitaly!1914
-rw-r--r--internal/prometheus/metrics/metrics.go6
-rw-r--r--internal/service/register.go80
-rw-r--r--internal/service/smarthttp/server.go44
-rw-r--r--internal/service/smarthttp/testhelper_test.go4
-rw-r--r--internal/service/smarthttp/upload_pack.go35
-rw-r--r--internal/service/smarthttp/upload_pack_test.go17
-rw-r--r--internal/service/ssh/server.go26
-rw-r--r--internal/service/ssh/upload_pack.go34
-rw-r--r--internal/service/ssh/upload_pack_test.go28
-rw-r--r--internal/testhelper/promtest/counter.go26
10 files changed, 266 insertions, 34 deletions
diff --git a/internal/prometheus/metrics/metrics.go b/internal/prometheus/metrics/metrics.go
index 9ca576de6..62b72d374 100644
--- a/internal/prometheus/metrics/metrics.go
+++ b/internal/prometheus/metrics/metrics.go
@@ -4,6 +4,12 @@ import (
"github.com/prometheus/client_golang/prometheus"
)
+// Counter is a subset of a prometheus Counter
+type Counter interface {
+ Inc()
+ Add(float64)
+}
+
// Gauge is a subset of a prometheus Gauge
type Gauge interface {
Inc()
diff --git a/internal/service/register.go b/internal/service/register.go
index 992ebee45..eb5c9c2cd 100644
--- a/internal/service/register.go
+++ b/internal/service/register.go
@@ -1,6 +1,7 @@
package service
import (
+ "github.com/prometheus/client_golang/prometheus"
"gitlab.com/gitlab-org/gitaly/internal/config"
"gitlab.com/gitlab-org/gitaly/internal/rubyserver"
"gitlab.com/gitlab-org/gitaly/internal/service/blob"
@@ -26,6 +27,73 @@ import (
healthpb "google.golang.org/grpc/health/grpc_health_v1"
)
+var (
+ smarthttpDeepensMetric = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "gitaly",
+ Subsystem: "smarthttp",
+ Name: "deepen_requests_total",
+ Help: "Number of git-upload-pack requests processed that contained a 'deepen' message",
+ },
+ )
+
+ smarthttpFiltersMetric = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "gitaly",
+ Subsystem: "smarthttp",
+ Name: "filter_requests_total",
+ Help: "Number of git-upload-pack requests processed that contained a 'filter' message",
+ },
+ )
+
+ smarthttpHavesMetric = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "gitaly",
+ Subsystem: "smarthttp",
+ Name: "haves_requests_total",
+ Help: "Number of git-upload-pack requests processed that contained a 'have' message",
+ },
+ )
+
+ sshDeepensMetric = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "gitaly",
+ Subsystem: "ssh",
+ Name: "deepen_requests_total",
+ Help: "Number of git-upload-pack requests processed that contained a 'deepen' message",
+ },
+ )
+
+ sshFiltersMetric = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "gitaly",
+ Subsystem: "ssh",
+ Name: "filter_requests_total",
+ Help: "Number of git-upload-pack requests processed that contained a 'filter' message",
+ },
+ )
+
+ sshHavesMetric = prometheus.NewCounter(
+ prometheus.CounterOpts{
+ Namespace: "gitaly",
+ Subsystem: "ssh",
+ Name: "haves_requests_total",
+ Help: "Number of git-upload-pack requests processed that contained a 'have' message",
+ },
+ )
+)
+
+func init() {
+ prometheus.MustRegister(
+ smarthttpDeepensMetric,
+ smarthttpFiltersMetric,
+ smarthttpHavesMetric,
+ sshDeepensMetric,
+ sshFiltersMetric,
+ sshHavesMetric,
+ )
+}
+
// RegisterAll will register all the known grpc services with
// the specified grpc service instance
func RegisterAll(grpcServer *grpc.Server, rubyServer *rubyserver.Server) {
@@ -37,8 +105,16 @@ func RegisterAll(grpcServer *grpc.Server, rubyServer *rubyserver.Server) {
gitalypb.RegisterOperationServiceServer(grpcServer, operations.NewServer(rubyServer))
gitalypb.RegisterRefServiceServer(grpcServer, ref.NewServer())
gitalypb.RegisterRepositoryServiceServer(grpcServer, repository.NewServer(rubyServer, config.GitalyInternalSocketPath()))
- gitalypb.RegisterSSHServiceServer(grpcServer, ssh.NewServer())
- gitalypb.RegisterSmartHTTPServiceServer(grpcServer, smarthttp.NewServer())
+ gitalypb.RegisterSSHServiceServer(grpcServer, ssh.NewServer(
+ ssh.WithDeepensMetric(sshDeepensMetric),
+ ssh.WithHavesMetric(sshHavesMetric),
+ ssh.WithFiltersMetric(sshFiltersMetric),
+ ))
+ gitalypb.RegisterSmartHTTPServiceServer(grpcServer, smarthttp.NewServer(
+ smarthttp.WithDeepensMetric(smarthttpDeepensMetric),
+ smarthttp.WithFiltersMetric(smarthttpFiltersMetric),
+ smarthttp.WithHavesMetric(smarthttpHavesMetric),
+ ))
gitalypb.RegisterWikiServiceServer(grpcServer, wiki.NewServer(rubyServer))
gitalypb.RegisterConflictsServiceServer(grpcServer, conflicts.NewServer(rubyServer))
gitalypb.RegisterRemoteServiceServer(grpcServer, remote.NewServer(rubyServer))
diff --git a/internal/service/smarthttp/server.go b/internal/service/smarthttp/server.go
index 5de729c22..b00dbb043 100644
--- a/internal/service/smarthttp/server.go
+++ b/internal/service/smarthttp/server.go
@@ -1,12 +1,50 @@
package smarthttp
-import "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+import (
+ "github.com/prometheus/client_golang/prometheus"
+ "gitlab.com/gitlab-org/gitaly/internal/prometheus/metrics"
+ "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
+)
type server struct {
+ deepensMetric metrics.Counter
+ filtersMetric metrics.Counter
+ havesMetric metrics.Counter
gitalypb.UnimplementedSmartHTTPServiceServer
}
// NewServer creates a new instance of a grpc SmartHTTPServer
-func NewServer() gitalypb.SmartHTTPServiceServer {
- return &server{}
+func NewServer(serverOpts ...ServerOpt) gitalypb.SmartHTTPServiceServer {
+ s := &server{
+ deepensMetric: prometheus.NewCounter(prometheus.CounterOpts{}),
+ filtersMetric: prometheus.NewCounter(prometheus.CounterOpts{}),
+ havesMetric: prometheus.NewCounter(prometheus.CounterOpts{}),
+ }
+
+ for _, serverOpt := range serverOpts {
+ serverOpt(s)
+ }
+
+ return s
+}
+
+// ServerOpt is a self referential option for server
+type ServerOpt func(s *server)
+
+func WithDeepensMetric(c metrics.Counter) ServerOpt {
+ return func(s *server) {
+ s.deepensMetric = c
+ }
+}
+
+func WithFiltersMetric(c metrics.Counter) ServerOpt {
+ return func(s *server) {
+ s.filtersMetric = c
+ }
+}
+
+func WithHavesMetric(c metrics.Counter) ServerOpt {
+ return func(s *server) {
+ s.havesMetric = c
+ }
}
diff --git a/internal/service/smarthttp/testhelper_test.go b/internal/service/smarthttp/testhelper_test.go
index aef5803ce..587c7bc72 100644
--- a/internal/service/smarthttp/testhelper_test.go
+++ b/internal/service/smarthttp/testhelper_test.go
@@ -28,10 +28,10 @@ func testMain(m *testing.M) int {
return m.Run()
}
-func runSmartHTTPServer(t *testing.T) (string, func()) {
+func runSmartHTTPServer(t *testing.T, serverOpts ...ServerOpt) (string, func()) {
srv := testhelper.NewServer(t, nil, nil)
- gitalypb.RegisterSmartHTTPServiceServer(srv.GrpcServer(), NewServer())
+ gitalypb.RegisterSmartHTTPServiceServer(srv.GrpcServer(), NewServer(serverOpts...))
reflection.Register(srv.GrpcServer())
require.NoError(t, srv.Start())
diff --git a/internal/service/smarthttp/upload_pack.go b/internal/service/smarthttp/upload_pack.go
index e43add012..db18176e4 100644
--- a/internal/service/smarthttp/upload_pack.go
+++ b/internal/service/smarthttp/upload_pack.go
@@ -6,7 +6,6 @@ import (
"io"
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
- "github.com/prometheus/client_golang/prometheus"
"gitlab.com/gitlab-org/gitaly/internal/command"
"gitlab.com/gitlab-org/gitaly/internal/git"
"gitlab.com/gitlab-org/gitaly/internal/git/stats"
@@ -19,19 +18,6 @@ import (
"google.golang.org/grpc/status"
)
-var (
- deepenCount = prometheus.NewCounter(
- prometheus.CounterOpts{
- Name: "gitaly_smarthttp_deepen_requests_total",
- Help: "Number of git-upload-pack requests processed that contained a 'deepen' message",
- },
- )
-)
-
-func init() {
- prometheus.MustRegister(deepenCount)
-}
-
func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackServer) error {
ctx := stream.Context()
@@ -58,10 +44,24 @@ func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackS
statsCh := make(chan stats.PackfileNegotiation, 1)
go func() {
defer close(statsCh)
- stats := stats.PackfileNegotiation{}
- if err := stats.Parse(pr); err == nil {
- statsCh <- stats
+
+ stats, err := stats.ParsePackfileNegotiation(pr)
+ if err != nil {
+ grpc_logrus.Extract(stream.Context()).WithError(err).Debug("failed parsing packfile negotiation")
+ return
}
+
+ if stats.Deepen != "" {
+ s.deepensMetric.Inc()
+ }
+ if stats.Filter != "" {
+ s.filtersMetric.Inc()
+ }
+ if len(stats.Haves) > 0 {
+ s.havesMetric.Inc()
+ }
+
+ statsCh <- stats
}()
var respBytes int64
@@ -112,7 +112,6 @@ func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackS
// We have seen a 'deepen' message in the request. It is expected that
// git-upload-pack has a non-zero exit status: don't treat this as an
// error.
- deepenCount.Inc()
return nil
}
diff --git a/internal/service/smarthttp/upload_pack_test.go b/internal/service/smarthttp/upload_pack_test.go
index aa1282e67..57a0f04f5 100644
--- a/internal/service/smarthttp/upload_pack_test.go
+++ b/internal/service/smarthttp/upload_pack_test.go
@@ -19,6 +19,7 @@ import (
"gitlab.com/gitlab-org/gitaly/internal/helper"
"gitlab.com/gitlab-org/gitaly/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
+ "gitlab.com/gitlab-org/gitaly/internal/testhelper/promtest"
"gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitaly/streamio"
"google.golang.org/grpc/codes"
@@ -29,7 +30,11 @@ const (
)
func TestSuccessfulUploadPackRequest(t *testing.T) {
- serverSocketPath, stop := runSmartHTTPServer(t)
+ haves := &promtest.MockCounter{}
+
+ serverSocketPath, stop := runSmartHTTPServer(
+ t, WithHavesMetric(haves),
+ )
defer stop()
ctx, cancel := testhelper.Context()
@@ -92,6 +97,8 @@ func TestSuccessfulUploadPackRequest(t *testing.T) {
// The fact that this command succeeds means that we got the commit correctly, no further checks should be needed.
testhelper.MustRunCommand(t, nil, "git", "-C", localRepoPath, "show", string(newHead))
+
+ require.Equal(t, 1.0, haves.Value())
}
func TestUploadPackRequestWithGitConfigOptions(t *testing.T) {
@@ -324,7 +331,11 @@ func extractPackDataFromResponse(t *testing.T, buf *bytes.Buffer) ([]byte, int,
}
func TestUploadPackRequestForPartialCloneSuccess(t *testing.T) {
- serverSocketPath, stop := runSmartHTTPServer(t)
+ filter := &promtest.MockCounter{}
+
+ serverSocketPath, stop := runSmartHTTPServer(
+ t, WithFiltersMetric(filter),
+ )
defer stop()
testRepo := testhelper.TestRepository()
@@ -418,4 +429,6 @@ func TestUploadPackRequestForPartialCloneSuccess(t *testing.T) {
_, err = makePostUploadPackRequest(ctx, t, serverSocketPath, req, &requestBuffer)
require.NoError(t, err)
+
+ require.Equal(t, 2.0, filter.Value())
}
diff --git a/internal/service/ssh/server.go b/internal/service/ssh/server.go
index 6933b76b6..808877f1f 100644
--- a/internal/service/ssh/server.go
+++ b/internal/service/ssh/server.go
@@ -3,6 +3,8 @@ package ssh
import (
"time"
+ "github.com/prometheus/client_golang/prometheus"
+ "gitlab.com/gitlab-org/gitaly/internal/prometheus/metrics"
"gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
)
@@ -14,6 +16,9 @@ var (
type server struct {
uploadPackRequestTimeout time.Duration
uploadArchiveRequestTimeout time.Duration
+ havesMetric metrics.Counter
+ deepensMetric metrics.Counter
+ filtersMetric metrics.Counter
gitalypb.UnimplementedSSHServiceServer
}
@@ -22,6 +27,9 @@ func NewServer(serverOpts ...ServerOpt) gitalypb.SSHServiceServer {
s := &server{
uploadPackRequestTimeout: defaultUploadPackRequestTimeout,
uploadArchiveRequestTimeout: defaultUploadArchiveRequestTimeout,
+ deepensMetric: prometheus.NewCounter(prometheus.CounterOpts{}),
+ filtersMetric: prometheus.NewCounter(prometheus.CounterOpts{}),
+ havesMetric: prometheus.NewCounter(prometheus.CounterOpts{}),
}
for _, serverOpt := range serverOpts {
@@ -47,3 +55,21 @@ func WithArchiveRequestTimeout(d time.Duration) ServerOpt {
s.uploadArchiveRequestTimeout = d
}
}
+
+func WithHavesMetric(c metrics.Counter) ServerOpt {
+ return func(s *server) {
+ s.havesMetric = c
+ }
+}
+
+func WithDeepensMetric(c metrics.Counter) ServerOpt {
+ return func(s *server) {
+ s.deepensMetric = c
+ }
+}
+
+func WithFiltersMetric(c metrics.Counter) ServerOpt {
+ return func(s *server) {
+ s.filtersMetric = c
+ }
+}
diff --git a/internal/service/ssh/upload_pack.go b/internal/service/ssh/upload_pack.go
index 94161fead..854eff492 100644
--- a/internal/service/ssh/upload_pack.go
+++ b/internal/service/ssh/upload_pack.go
@@ -3,12 +3,15 @@ package ssh
import (
"context"
"fmt"
+ "io"
+ "sync"
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
log "github.com/sirupsen/logrus"
"gitlab.com/gitlab-org/gitaly/internal/command"
"gitlab.com/gitlab-org/gitaly/internal/git"
"gitlab.com/gitlab-org/gitaly/internal/git/pktline"
+ "gitlab.com/gitlab-org/gitaly/internal/git/stats"
"gitlab.com/gitlab-org/gitaly/internal/helper"
"gitlab.com/gitlab-org/gitaly/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/internal/service/inspect"
@@ -83,6 +86,34 @@ func (s *server) sshUploadPack(stream gitalypb.SSHService_SSHUploadPackServer, r
globalOpts = append(globalOpts, git.ValueFlag{"-c", o})
}
+ pr, pw := io.Pipe()
+ defer pw.Close()
+ stdin = io.TeeReader(stdin, pw)
+ wg := sync.WaitGroup{}
+
+ wg.Add(1)
+ go func() {
+ defer func() {
+ wg.Done()
+ pr.Close()
+ }()
+
+ stats, err := stats.ParsePackfileNegotiation(pr)
+ if err != nil {
+ grpc_logrus.Extract(stream.Context()).WithError(err).Debug("failed parsing packfile negotiation")
+ return
+ }
+ if stats.Deepen != "" {
+ s.deepensMetric.Inc()
+ }
+ if stats.Filter != "" {
+ s.filtersMetric.Inc()
+ }
+ if len(stats.Haves) > 0 {
+ s.havesMetric.Inc()
+ }
+ }()
+
cmd, monitor, err := monitorStdinCommand(ctx, stdin, stdout, stderr, env, globalOpts, git.SubCmd{
Name: "upload-pack",
Args: []string{repoPath},
@@ -108,6 +139,9 @@ func (s *server) sshUploadPack(stream gitalypb.SSHService_SSHUploadPackServer, r
return fmt.Errorf("cmd wait: %v", err)
}
+ pw.Close()
+ wg.Wait()
+
return nil
}
diff --git a/internal/service/ssh/upload_pack_test.go b/internal/service/ssh/upload_pack_test.go
index 04a53b357..447b9c8df 100644
--- a/internal/service/ssh/upload_pack_test.go
+++ b/internal/service/ssh/upload_pack_test.go
@@ -17,6 +17,7 @@ import (
"gitlab.com/gitlab-org/gitaly/internal/helper/text"
"gitlab.com/gitlab-org/gitaly/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
+ "gitlab.com/gitlab-org/gitaly/internal/testhelper/promtest"
"gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
"google.golang.org/grpc/codes"
)
@@ -185,22 +186,31 @@ func TestFailedUploadPackRequestDueToValidationError(t *testing.T) {
}
func TestUploadPackCloneSuccess(t *testing.T) {
- serverSocketPath, stop := runSSHServer(t)
+ deepen := &promtest.MockCounter{}
+ filter := &promtest.MockCounter{}
+ haves := &promtest.MockCounter{}
+
+ serverSocketPath, stop := runSSHServer(
+ t, WithDeepensMetric(deepen), WithFiltersMetric(filter), WithHavesMetric(haves),
+ )
defer stop()
localRepoPath := path.Join(testRepoRoot, "gitlab-test-upload-pack-local")
tests := []struct {
- cmd *exec.Cmd
- desc string
+ cmd *exec.Cmd
+ desc string
+ deepen float64
}{
{
- cmd: exec.Command("git", "clone", "git@localhost:test/test.git", localRepoPath),
- desc: "full clone",
+ cmd: exec.Command("git", "clone", "git@localhost:test/test.git", localRepoPath),
+ desc: "full clone",
+ deepen: 0,
},
{
- cmd: exec.Command("git", "clone", "--depth", "1", "git@localhost:test/test.git", localRepoPath),
- desc: "shallow clone",
+ cmd: exec.Command("git", "clone", "--depth", "1", "git@localhost:test/test.git", localRepoPath),
+ desc: "shallow clone",
+ deepen: 1,
},
}
@@ -213,6 +223,10 @@ func TestUploadPackCloneSuccess(t *testing.T) {
}
lHead, rHead, _, _ := cmd.test(t, localRepoPath)
require.Equal(t, lHead, rHead, "local and remote head not equal")
+
+ require.Equal(t, deepen.Value(), tc.deepen)
+ require.Equal(t, filter.Value(), 0.0)
+ require.Equal(t, haves.Value(), 0.0)
})
}
}
diff --git a/internal/testhelper/promtest/counter.go b/internal/testhelper/promtest/counter.go
new file mode 100644
index 000000000..665023436
--- /dev/null
+++ b/internal/testhelper/promtest/counter.go
@@ -0,0 +1,26 @@
+package promtest
+
+import (
+ "sync"
+)
+
+type MockCounter struct {
+ m sync.RWMutex
+ value float64
+}
+
+func (m *MockCounter) Value() float64 {
+ m.m.RLock()
+ defer m.m.RUnlock()
+ return m.value
+}
+
+func (m *MockCounter) Inc() {
+ m.Add(1)
+}
+
+func (m *MockCounter) Add(v float64) {
+ m.m.Lock()
+ defer m.m.Unlock()
+ m.value += v
+}