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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse/internal/upstream')
-rw-r--r--workhorse/internal/upstream/.gitignore1
-rw-r--r--workhorse/internal/upstream/metrics.go103
-rw-r--r--workhorse/internal/upstream/routes.go27
-rw-r--r--workhorse/internal/upstream/routes_test.go30
4 files changed, 55 insertions, 106 deletions
diff --git a/workhorse/internal/upstream/.gitignore b/workhorse/internal/upstream/.gitignore
new file mode 100644
index 00000000000..d63cd8b2c40
--- /dev/null
+++ b/workhorse/internal/upstream/.gitignore
@@ -0,0 +1 @@
+testdata/public
diff --git a/workhorse/internal/upstream/metrics.go b/workhorse/internal/upstream/metrics.go
index 1a11bdc8b53..27cc6bb045b 100644
--- a/workhorse/internal/upstream/metrics.go
+++ b/workhorse/internal/upstream/metrics.go
@@ -6,6 +6,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
+
+ "gitlab.com/gitlab-org/labkit/metrics"
)
const (
@@ -13,95 +15,7 @@ const (
httpSubsystem = "http"
)
-func secondsDurationBuckets() []float64 {
- return []float64{
- 0.005, /* 5ms */
- 0.025, /* 25ms */
- 0.1, /* 100ms */
- 0.5, /* 500ms */
- 1.0, /* 1s */
- 10.0, /* 10s */
- 30.0, /* 30s */
- 60.0, /* 1m */
- 300.0, /* 10m */
- }
-}
-
-func byteSizeBuckets() []float64 {
- return []float64{
- 10,
- 64,
- 256,
- 1024, /* 1kB */
- 64 * 1024, /* 64kB */
- 256 * 1024, /* 256kB */
- 1024 * 1024, /* 1mB */
- 64 * 1024 * 1024, /* 64mB */
- }
-}
-
var (
- httpInFlightRequests = promauto.NewGauge(prometheus.GaugeOpts{
- Namespace: namespace,
- Subsystem: httpSubsystem,
- Name: "in_flight_requests",
- Help: "A gauge of requests currently being served by workhorse.",
- })
-
- httpRequestsTotal = promauto.NewCounterVec(
- prometheus.CounterOpts{
- Namespace: namespace,
- Subsystem: httpSubsystem,
- Name: "requests_total",
- Help: "A counter for requests to workhorse.",
- },
- []string{"code", "method", "route"},
- )
-
- httpRequestDurationSeconds = promauto.NewHistogramVec(
- prometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: httpSubsystem,
- Name: "request_duration_seconds",
- Help: "A histogram of latencies for requests to workhorse.",
- Buckets: secondsDurationBuckets(),
- },
- []string{"code", "method", "route"},
- )
-
- httpRequestSizeBytes = promauto.NewHistogramVec(
- prometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: httpSubsystem,
- Name: "request_size_bytes",
- Help: "A histogram of sizes of requests to workhorse.",
- Buckets: byteSizeBuckets(),
- },
- []string{"code", "method", "route"},
- )
-
- httpResponseSizeBytes = promauto.NewHistogramVec(
- prometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: httpSubsystem,
- Name: "response_size_bytes",
- Help: "A histogram of response sizes for requests to workhorse.",
- Buckets: byteSizeBuckets(),
- },
- []string{"code", "method", "route"},
- )
-
- httpTimeToWriteHeaderSeconds = promauto.NewHistogramVec(
- prometheus.HistogramOpts{
- Namespace: namespace,
- Subsystem: httpSubsystem,
- Name: "time_to_write_header_seconds",
- Help: "A histogram of request durations until the response headers are written.",
- Buckets: secondsDurationBuckets(),
- },
- []string{"code", "method", "route"},
- )
-
httpGeoProxiedRequestsTotal = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
@@ -111,19 +25,12 @@ var (
},
[]string{"code", "method", "route"},
)
+
+ buildHandler = metrics.NewHandlerFactory(metrics.WithNamespace(namespace), metrics.WithLabels("route"))
)
func instrumentRoute(next http.Handler, method string, regexpStr string) http.Handler {
- handler := next
-
- handler = promhttp.InstrumentHandlerCounter(httpRequestsTotal.MustCurryWith(map[string]string{"route": regexpStr}), handler)
- handler = promhttp.InstrumentHandlerDuration(httpRequestDurationSeconds.MustCurryWith(map[string]string{"route": regexpStr}), handler)
- handler = promhttp.InstrumentHandlerInFlight(httpInFlightRequests, handler)
- handler = promhttp.InstrumentHandlerRequestSize(httpRequestSizeBytes.MustCurryWith(map[string]string{"route": regexpStr}), handler)
- handler = promhttp.InstrumentHandlerResponseSize(httpResponseSizeBytes.MustCurryWith(map[string]string{"route": regexpStr}), handler)
- handler = promhttp.InstrumentHandlerTimeToWriteHeader(httpTimeToWriteHeaderSeconds.MustCurryWith(map[string]string{"route": regexpStr}), handler)
-
- return handler
+ return buildHandler(next, metrics.WithLabelValues(map[string]string{"route": regexpStr}))
}
func instrumentGeoProxyRoute(next http.Handler, method string, regexpStr string) http.Handler {
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index b8089865ffe..b1d76dfc1bd 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -20,7 +20,6 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/git"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/imageresizer"
- "gitlab.com/gitlab-org/gitlab/workhorse/internal/lfs"
proxypkg "gitlab.com/gitlab-org/gitlab/workhorse/internal/proxy"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/queueing"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/redis"
@@ -251,8 +250,8 @@ func configureRoutes(u *upstream) {
u.route("PUT", gitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`, upload.RequestBody(api, signingProxy, preparers.lfs), withMatcher(isContentType("application/octet-stream"))),
// CI Artifacts
- u.route("POST", apiPattern+`v4/jobs/[0-9]+/artifacts\z`, contentEncodingHandler(artifacts.UploadArtifacts(api, signingProxy, preparers.artifacts))),
- u.route("POST", ciAPIPattern+`v1/builds/[0-9]+/artifacts\z`, contentEncodingHandler(artifacts.UploadArtifacts(api, signingProxy, preparers.artifacts))),
+ u.route("POST", apiPattern+`v4/jobs/[0-9]+/artifacts\z`, contentEncodingHandler(upload.Artifacts(api, signingProxy, preparers.artifacts))),
+ u.route("POST", ciAPIPattern+`v1/builds/[0-9]+/artifacts\z`, contentEncodingHandler(upload.Artifacts(api, signingProxy, preparers.artifacts))),
// ActionCable websocket
u.wsRoute(`^/-/cable\z`, cableProxy),
@@ -318,9 +317,12 @@ func configureRoutes(u *upstream) {
// Group Import via UI upload acceleration
u.route("POST", importPattern+`gitlab_group`, upload.Multipart(api, signingProxy, preparers.uploads)),
- // Metric image upload
+ // Issuable Metric image upload
u.route("POST", apiProjectPattern+`issues/[0-9]+/metric_images\z`, upload.Multipart(api, signingProxy, preparers.uploads)),
+ // Alert Metric image upload
+ u.route("POST", apiProjectPattern+`alert_management_alerts/[0-9]+/metric_images\z`, upload.Multipart(api, signingProxy, preparers.uploads)),
+
// Requirements Import via UI upload acceleration
u.route("POST", projectPattern+`requirements_management/requirements/import_csv`, upload.Multipart(api, signingProxy, preparers.uploads)),
@@ -383,11 +385,10 @@ func configureRoutes(u *upstream) {
u.route("", "^/oauth/geo/(auth|callback|logout)$", defaultUpstream),
// Admin Area > Geo routes
- u.route("", "^/admin/geo$", defaultUpstream),
- u.route("", "^/admin/geo/", defaultUpstream),
+ u.route("", "^/admin/geo/replication/projects", defaultUpstream),
+ u.route("", "^/admin/geo/replication/designs", defaultUpstream),
// Geo API routes
- u.route("", "^/api/v4/geo_nodes", defaultUpstream),
u.route("", "^/api/v4/geo_replication", defaultUpstream),
u.route("", "^/api/v4/geo/proxy_git_ssh", defaultUpstream),
u.route("", "^/api/v4/geo/graphql", defaultUpstream),
@@ -395,6 +396,16 @@ func configureRoutes(u *upstream) {
// Internal API routes
u.route("", "^/api/v4/internal", defaultUpstream),
+ u.route(
+ "", `^/assets/`,
+ static.ServeExisting(
+ u.URLPrefix,
+ staticpages.CacheExpireMax,
+ assetsNotFoundHandler,
+ ),
+ withoutTracing(), // Tracing on assets is very noisy
+ ),
+
// Don't define a catch-all route. If a route does not match, then we know
// the request should be proxied.
}
@@ -405,7 +416,7 @@ func createUploadPreparers(cfg config.Config) uploadPreparers {
return uploadPreparers{
artifacts: defaultPreparer,
- lfs: lfs.NewLfsUploadPreparer(cfg, defaultPreparer),
+ lfs: upload.NewLfsPreparer(cfg, defaultPreparer),
packages: defaultPreparer,
uploads: defaultPreparer,
}
diff --git a/workhorse/internal/upstream/routes_test.go b/workhorse/internal/upstream/routes_test.go
index f196433f5b4..8a032519bdf 100644
--- a/workhorse/internal/upstream/routes_test.go
+++ b/workhorse/internal/upstream/routes_test.go
@@ -2,8 +2,26 @@ package upstream
import (
"testing"
+
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/testhelper"
)
+func TestAdminGeoPathsWithGeoProxy(t *testing.T) {
+ testCases := []testCase{
+ {"Regular admin/geo", "/admin/geo", "Geo primary received request to path /admin/geo"},
+ {"Specific object replication", "/admin/geo/replication/object_type", "Geo primary received request to path /admin/geo/replication/object_type"},
+ {"Specific object replication per-site", "/admin/geo/sites/2/replication/object_type", "Geo primary received request to path /admin/geo/sites/2/replication/object_type"},
+ {"Projects replication per-site", "/admin/geo/sites/2/replication/projects", "Geo primary received request to path /admin/geo/sites/2/replication/projects"},
+ {"Designs replication per-site", "/admin/geo/sites/2/replication/designs", "Geo primary received request to path /admin/geo/sites/2/replication/designs"},
+ {"Projects replication", "/admin/geo/replication/projects", "Local Rails server received request to path /admin/geo/replication/projects"},
+ {"Projects replication subpaths", "/admin/geo/replication/projects/2", "Local Rails server received request to path /admin/geo/replication/projects/2"},
+ {"Designs replication", "/admin/geo/replication/designs", "Local Rails server received request to path /admin/geo/replication/designs"},
+ {"Designs replication subpaths", "/admin/geo/replication/designs/3", "Local Rails server received request to path /admin/geo/replication/designs/3"},
+ }
+
+ runTestCasesWithGeoProxyEnabled(t, testCases)
+}
+
func TestProjectNotExistingGitHttpPullWithGeoProxy(t *testing.T) {
testCases := []testCase{
{"secondary info/refs", "/group/project.git/info/refs", "Local Rails server received request to path /group/project.git/info/refs"},
@@ -45,3 +63,15 @@ func TestProjectNotExistingGitSSHPushWithGeoProxy(t *testing.T) {
runTestCasesWithGeoProxyEnabled(t, testCases)
}
+
+func TestAssetsServedLocallyWithGeoProxy(t *testing.T) {
+ path := "/assets/static.txt"
+ content := "local geo asset"
+ testhelper.SetupStaticFileHelper(t, path, content, testDocumentRoot)
+
+ testCases := []testCase{
+ {"assets path", "/assets/static.txt", "local geo asset"},
+ }
+
+ runTestCasesWithGeoProxyEnabled(t, testCases)
+}