diff --git a/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue b/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue
index 2874d89d913..d5dac1e8fb6 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue
@@ -71,7 +71,7 @@ export default {
>
diff --git a/app/assets/javascripts/snippets/components/show.vue b/app/assets/javascripts/snippets/components/show.vue
index ae259b10648..430c701ae95 100644
--- a/app/assets/javascripts/snippets/components/show.vue
+++ b/app/assets/javascripts/snippets/components/show.vue
@@ -50,9 +50,7 @@ export default {
data-qa-selector="clone_button"
/>
-
-
-
+
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_view.vue b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
index 63c95daae5d..b38be5bb9a4 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
@@ -25,8 +25,9 @@ export default {
rich: this.activeViewerType === RICH_BLOB_VIEWER,
};
},
- update: data =>
- data.snippets.edges[0].node.blob.richData || data.snippets.edges[0].node.blob.plainData,
+ update(data) {
+ return this.onContentUpdate(data);
+ },
result() {
if (this.activeViewerType === RICH_BLOB_VIEWER) {
this.blob.richViewer.renderError = null;
@@ -76,6 +77,12 @@ export default {
this.$apollo.queries.blobContent.skip = false;
this.$apollo.queries.blobContent.refetch();
},
+ onContentUpdate(data) {
+ const { path: blobPath } = this.blob;
+ const { blobs } = data.snippets.edges[0].node;
+ const updatedBlobData = blobs.find(blob => blob.path === blobPath);
+ return updatedBlobData.richData || updatedBlobData.plainData;
+ },
},
BLOB_RENDER_EVENT_LOAD,
BLOB_RENDER_EVENT_SHOW_SOURCE,
diff --git a/app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql b/app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql
index 889a88dd93c..8f1f16b76c2 100644
--- a/app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql
+++ b/app/assets/javascripts/snippets/queries/snippet.blob.content.query.graphql
@@ -3,7 +3,8 @@ query SnippetBlobContent($ids: [ID!], $rich: Boolean!) {
edges {
node {
id
- blob {
+ blobs {
+ path
richData @include(if: $rich)
plainData @skip(if: $rich)
}
diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss
index dbcb5086d70..4c1c9d15121 100644
--- a/app/assets/stylesheets/framework/snippets.scss
+++ b/app/assets/stylesheets/framework/snippets.scss
@@ -32,6 +32,10 @@
.snippet-file-content {
border-radius: 3px;
+
+ + .snippet-file-content {
+ @include gl-mt-5;
+ }
}
.snippet-header {
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index d1b8d298f67..145e4a808e2 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -36,6 +36,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:multiline_comments, @project)
push_frontend_feature_flag(:file_identifier_hash)
push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true)
+ push_frontend_feature_flag(:auto_expand_collapsed_diffs, @project)
end
before_action do
diff --git a/app/services/issuable/common_system_notes_service.rb b/app/services/issuable/common_system_notes_service.rb
index 195616857dc..84024cca68c 100644
--- a/app/services/issuable/common_system_notes_service.rb
+++ b/app/services/issuable/common_system_notes_service.rb
@@ -108,7 +108,7 @@ module Issuable
end
def milestone_changes_tracking_enabled?
- ::Feature.enabled?(:track_resource_milestone_change_events, issuable.project)
+ ::Feature.enabled?(:track_resource_milestone_change_events, issuable.project, default_enabled: true)
end
def create_due_date_note
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index 76261aa716e..7535db54130 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -341,7 +341,7 @@ module SystemNotes
def state_change_tracking_enabled?
noteable.respond_to?(:resource_state_events) &&
- ::Feature.enabled?(:track_resource_state_change_events, noteable.project)
+ ::Feature.enabled?(:track_resource_state_change_events, noteable.project, default_enabled: true)
end
end
end
diff --git a/changelogs/unreleased/219029-refactor-metrics-tranasction.yml b/changelogs/unreleased/219029-refactor-metrics-tranasction.yml
new file mode 100644
index 00000000000..f3cd700ee96
--- /dev/null
+++ b/changelogs/unreleased/219029-refactor-metrics-tranasction.yml
@@ -0,0 +1,5 @@
+---
+title: Unify Prometheus metric initialization by always using inline transaction metrics
+merge_request: 32980
+author:
+type: other
diff --git a/changelogs/unreleased/222469-view-your-composer-dependencies-in-the-package-registry-ui.yml b/changelogs/unreleased/222469-view-your-composer-dependencies-in-the-package-registry-ui.yml
new file mode 100644
index 00000000000..e0ffd498452
--- /dev/null
+++ b/changelogs/unreleased/222469-view-your-composer-dependencies-in-the-package-registry-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Add composer tab and package type to package list
+merge_request: 37928
+author:
+type: changed
diff --git a/changelogs/unreleased/229147-enable-milestone-weight-events-feature-flag.yml b/changelogs/unreleased/229147-enable-milestone-weight-events-feature-flag.yml
new file mode 100644
index 00000000000..7ab6b63d078
--- /dev/null
+++ b/changelogs/unreleased/229147-enable-milestone-weight-events-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Track milestone and state changes in issues / MRs using resource events
+merge_request: 36936
+author:
+type: changed
diff --git a/changelogs/unreleased/229403-incident-search-bar.yml b/changelogs/unreleased/229403-incident-search-bar.yml
new file mode 100644
index 00000000000..55093b8023c
--- /dev/null
+++ b/changelogs/unreleased/229403-incident-search-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Add search bar for incidents
+merge_request: 37885
+author:
+type: changed
diff --git a/changelogs/unreleased/229978-can-t-see-image-names-in-the-container-registry-when-in-dark-mode.yml b/changelogs/unreleased/229978-can-t-see-image-names-in-the-container-registry-when-in-dark-mode.yml
new file mode 100644
index 00000000000..49b792cda5b
--- /dev/null
+++ b/changelogs/unreleased/229978-can-t-see-image-names-in-the-container-registry-when-in-dark-mode.yml
@@ -0,0 +1,5 @@
+---
+title: Fix dark mode container registry text
+merge_request: 37940
+author:
+type: fixed
diff --git a/config/initializers/zz_metrics.rb b/config/initializers/zz_metrics.rb
index 7e675e478cf..93f0f25d84b 100644
--- a/config/initializers/zz_metrics.rb
+++ b/config/initializers/zz_metrics.rb
@@ -199,7 +199,7 @@ if Gitlab::Metrics.enabled? && !Rails.env.test? && !(Rails.env.development? && d
val = super
if current_transaction = ::Gitlab::Metrics::Transaction.current
- current_transaction.increment(:new_redis_connections, 1)
+ current_transaction.increment(:gitlab_transaction_new_redis_connections_total, 1)
end
val
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index dbf2635dd6f..373517beed7 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -1,86 +1,49 @@
+---
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Reference architecture: up to 1,000 users
-This page describes GitLab reference architecture for up to 1,000 users.
-For a full list of reference architectures, see
+This page describes GitLab reference architecture for up to 1,000 users. For a
+full list of reference architectures, see
[Available reference architectures](index.md#available-reference-architectures).
+If you need to serve up to 1,000 users and you don't have strict availability
+requirements, a single-node solution with
+[frequent backups](index.md#automated-backups-core-only) is appropriate for
+many organizations .
+
> - **Supported users (approximate):** 1,000
-> - **High Availability:** False
+> - **High Availability:** No
-| Users | Configuration([8](#footnotes)) | GCP | AWS | Azure |
-|-------------|------------------------------------|----------------|---------------------|------------------------|
-| up to 500 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 |
-| up to 1000 | 8 vCPU, 7.2GB Memory | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 |
+| Users | Configuration | GCP | AWS | Azure |
+|--------------|-------------------------|----------------|-----------------|----------------|
+| Up to 500 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| Up to 1,000 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-In addition to the above, we recommend having at least
-2GB of swap on your server, even if you currently have
-enough available RAM. Having swap will help reduce the chance of errors occurring
-if your available memory changes. We also recommend
-configuring the kernel's swappiness setting
-to a low value like `10` to make the most of your RAM while still having the swap
-available when needed.
+The Google Cloud Platform (GCP) architectures were built and tested using the
+[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
+CPU platform. On different hardware you may find that adjustments, either lower
+or higher, are required for your CPU or node counts. For more information, see
+our [Sysbench](https://github.com/akopytov/sysbench)-based
+[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-For situations where you need to serve up to 1,000 users, a single-node
-solution with [frequent backups](index.md#automated-backups-core-only) is appropriate
-for many organizations. With automatic backup of the GitLab repositories,
-configuration, and the database, if you don't have strict availability
-requirements, this is the ideal solution.
+In addition to the stated configurations, we recommend having at least 2GB of
+swap on your server, even if you currently have enough available memory. Having
+swap will help reduce the chance of errors occurring if your available memory
+changes. We also recommend configuring the kernel's swappiness setting to a
+lower value (such as `10`) to make the most of your memory, while still having
+the swap available when needed.
## Setup instructions
-- For this default reference architecture, use the standard [installation instructions](../../install/README.md) to install GitLab.
+For this default reference architecture, to install GitLab use the standard
+[installation instructions](../../install/README.md).
NOTE: **Note:**
You can also optionally configure GitLab to use an
[external PostgreSQL service](../postgresql/external.md) or an
[external object storage service](../high_availability/object_storage.md) for
added performance and reliability at a reduced complexity cost.
-
-## Footnotes
-
-1. In our architectures we run each GitLab Rails node using the Puma webserver
- and have its number of workers set to 90% of available CPUs along with four threads. For
- nodes that are running Rails with other components the worker value should be reduced
- accordingly where we've found 50% achieves a good balance but this is dependent
- on workload.
-
-1. Gitaly node requirements are dependent on customer data, specifically the number of
- projects and their sizes. We recommend two nodes as an absolute minimum for HA environments
- and at least four nodes should be used when supporting 50,000 or more users.
- We also recommend that each Gitaly node should store no more than 5TB of data
- and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby)
- set to 20% of available CPUs. Additional nodes should be considered in conjunction
- with a review of expected data size and spread based on the recommendations above.
-
-1. Recommended Redis setup differs depending on the size of the architecture.
- For smaller architectures (less than 3,000 users) a single instance should suffice.
- For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all
- classes and that Redis Sentinel is hosted alongside Consul.
- For larger architectures (10,000 users or more) we suggest running a separate
- [Redis Cluster](../redis/replication_and_failover.md#running-multiple-redis-clusters) for the Cache class
- and another for the Queues and Shared State classes respectively. We also recommend
- that you run the Redis Sentinel clusters separately for each Redis Cluster.
-
-1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend an [Object Storage service](../object_storage.md)
- over NFS where possible, due to better performance and availability.
-
-1. NFS can be used as an alternative for both repository data (replacing Gitaly) and
- object storage but this isn't typically recommended for performance reasons. Note however it is required for
- [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196).
-
-1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/)
- as the load balancer. Although other load balancers with similar feature sets
- could also be used, those load balancers have not been validated.
-
-1. We strongly recommend that any Gitaly or NFS nodes be set up with SSD disks over
- HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write
- as these components have heavy I/O. These IOPS values are recommended only as a starter
- as with time they may be adjusted higher or lower depending on the scale of your
- environment's workload. If you're running the environment on a Cloud provider
- you may need to refer to their documentation on how configure IOPS correctly.
-
-1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
- CPU platform on GCP. On different hardware you may find that adjustments, either lower
- or higher, are required for your CPU or Node counts accordingly. For more information, a
- [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found
- [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index d182daf45b3..f88c07423eb 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -1,5 +1,8 @@
---
reading_time: true
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Reference architecture: up to 2,000 users
@@ -9,19 +12,19 @@ For a full list of reference architectures, see
[Available reference architectures](index.md#available-reference-architectures).
> - **Supported users (approximate):** 2,000
-> - **High Availability:** False
+> - **High Availability:** No
> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git: 4 RPS
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|------------------------------------------|--------|-------------------------|-----------------|----------------|-----------|
-| Load balancer | 1 | 2 vCPU, 1.8GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL | 1 | 2 vCPU, 7.5GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Redis | 1 | 1 vCPU, 3.75GB memory | `n1-standard-1` | `m5.large` | `D2s v3` |
-| Gitaly | 1 | 4 vCPU, 15GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| GitLab Rails | 2 | 8 vCPU, 7.2GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Monitoring node | 1 | 2 vCPU, 1.8GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Service | Nodes | Configuration | GCP | AWS | Azure |
+|------------------------------------------|--------|-------------------------|----------------|--------------|---------|
+| Load balancer | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| PostgreSQL | 1 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 |
+| Redis | 1 | 1 vCPU, 3.75GB memory | n1-standard-1 | m5.large | D2s v3 |
+| Gitaly | 1 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
+| GitLab Rails | 2 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Object storage | n/a | n/a | n/a | n/a | n/a |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
The Google Cloud Platform (GCP) architectures were built and tested using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 40b39db7a70..48abaf68669 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -1,49 +1,54 @@
---
reading_time: true
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Reference architecture: up to 3,000 users
-This page describes GitLab reference architecture for up to 3,000 users.
-For a full list of reference architectures, see
+This page describes GitLab reference architecture for up to 3,000 users. For a
+full list of reference architectures, see
[Available reference architectures](index.md#available-reference-architectures).
NOTE: **Note:**
-The 3,000-user reference architecture documented below is
-designed to help your organization achieve a highly-available GitLab deployment.
-If you do not have the expertise or need to maintain a highly-available
-environment, you can have a simpler and less costly-to-operate environment by
-following the [2,000-user reference architecture](2k_users.md).
+This reference architecture is designed to help your organization achieve a
+highly-available GitLab deployment. If you do not have the expertise or need to
+maintain a highly-available environment, you can have a simpler and less
+costly-to-operate environment by using the
+[2,000-user reference architecture](2k_users.md).
> - **Supported users (approximate):** 3,000
-> - **High Availability:** True
-> - **Test RPS rates:** API: 60 RPS, Web: 6 RPS, Git: 6 RPS
+> - **High Availability:** Yes
+> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git: 6 RPS
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|--------------------------------------------------------------|-------|---------------------------------|-----------------|-------------------------|----------------|
-| External load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul + Sentinel | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Gitaly | 2 minimum | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| GitLab Rails | 3 | 8 vCPU, 7.2GB Memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object Storage | n/a | n/a | n/a | n/a | n/a |
-| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Service | Nodes | Configuration | GCP | AWS | Azure |
+|--------------------------------------------|-------------|-----------------------|----------------|-------------|---------|
+| External load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Redis | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 |
+| Consul + Sentinel | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| PostgreSQL | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Internal load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Gitaly | 2 (minimum) | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
+| Sidekiq | 4 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 |
+| GitLab Rails | 3 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Object Storage | n/a | n/a | n/a | n/a | n/a |
+| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
-CPU platform on GCP. On different hardware you may find that adjustments, either lower
-or higher, are required for your CPU or Node counts accordingly. For more information, a
-[Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found
-[here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
+The Google Cloud Platform (GCP) architectures were built and tested using the
+[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
+CPU platform. On different hardware you may find that adjustments, either lower
+or higher, are required for your CPU or node counts. For more information, see
+our [Sysbench](https://github.com/akopytov/sysbench)-based
+[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-For data objects such as LFS, Uploads, Artifacts, etc, an [object storage service](#configure-the-object-storage)
-is recommended over NFS where possible, due to better performance and availability.
-Since this doesn't require a node to be set up, it's marked as not applicable (n/a)
-in the table above.
+For data objects (such as LFS, Uploads, or Artifacts), an
+[object storage service](#configure-the-object-storage) is recommended instead
+of NFS where possible, due to better performance and availability. Since this
+doesn't require a node to be set up, *Object Storage* is noted as not
+applicable (n/a) in the previous table.
## Setup components
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 0b4114bca6e..84f6c90d889 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -1,49 +1,54 @@
---
reading_time: true
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Reference architecture: up to 5,000 users
-This page describes GitLab reference architecture for up to 5,000 users.
-For a full list of reference architectures, see
+This page describes GitLab reference architecture for up to 5,000 users. For a
+full list of reference architectures, see
[Available reference architectures](index.md#available-reference-architectures).
NOTE: **Note:**
-The 5,000-user reference architecture documented below is
-designed to help your organization achieve a highly-available GitLab deployment.
-If you do not have the expertise or need to maintain a highly-available
-environment, you can have a simpler and less costly-to-operate environment by
-following the [2,000-user reference architecture](2k_users.md).
+This reference architecture is designed to help your organization achieve a
+highly-available GitLab deployment. If you do not have the expertise or need to
+maintain a highly-available environment, you can have a simpler and less
+costly-to-operate environment by using the
+[2,000-user reference architecture](2k_users.md).
> - **Supported users (approximate):** 5,000
-> - **High Availability:** True
-> - **Test RPS rates:** API: 100 RPS, Web: 10 RPS, Git: 10 RPS
+> - **High Availability:** Yes
+> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git: 10 RPS
-| Service | Nodes | Configuration | GCP | AWS | Azure |
-|--------------------------------------------------------------|-------|---------------------------------|-----------------|-----------------------|----------------|
-| External load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul + Sentinel | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Gitaly | 2 minimum | 8 vCPU, 30GB Memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
-| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| GitLab Rails | 3 | 16 vCPU, 14.4GB Memory | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2` |
-| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object Storage | n/a | n/a | n/a | n/a | n/a |
-| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Service | Nodes | Configuration | GCP | AWS | Azure |
+|--------------------------------------------|-------------|-------------------------|----------------|-------------|----------|
+| External load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Redis | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 |
+| Consul + Sentinel | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| PostgreSQL | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Internal load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Gitaly | 2 (minimum) | 8 vCPU, 30GB memory | n1-standard-8 | m5.2xlarge | D8s v3 |
+| Sidekiq | 4 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 |
+| GitLab Rails | 3 | 16 vCPU, 14.4GB memory | n1-highcpu-16 | c5.4xlarge | F16s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Object Storage | n/a | n/a | n/a | n/a | n/a |
+| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
-CPU platform on GCP. On different hardware you may find that adjustments, either lower
-or higher, are required for your CPU or Node counts accordingly. For more information, a
-[Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found
-[here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
+The Google Cloud Platform (GCP) architectures were built and tested using the
+[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
+CPU platform. On different hardware you may find that adjustments, either lower
+or higher, are required for your CPU or node counts. For more information, see
+our [Sysbench](https://github.com/akopytov/sysbench)-based
+[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-For data objects such as LFS, Uploads, Artifacts, etc, an [object storage service](#configure-the-object-storage)
-is recommended over NFS where possible, due to better performance and availability.
-Since this doesn't require a node to be set up, it's marked as not applicable (n/a)
-in the table above.
+For data objects (such as LFS, Uploads, or Artifacts), an
+[object storage service](#configure-the-object-storage) is recommended instead
+of NFS where possible, due to better performance and availability. Since this
+doesn't require a node to be set up, *Object Storage* is noted as not
+applicable (n/a) in the previous table.
## Setup components
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 9a75b950f28..6b25494c577 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -7,7 +7,19 @@ Notes are comments on:
- Merge requests
- Epics **(ULTIMATE)**
-This includes system notes, which are notes about changes to the object (for example, when a milestone changes, there will be a corresponding system note). Label notes are not part of this API, but recorded as separate events in [resource label events](resource_label_events.md).
+This includes system notes, which are notes about changes to the object (for example, when an
+assignee changes, there will be a corresponding system note).
+
+## Resource events
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38096) in GitLab 13.3 for state, milestone, and weight events.
+
+Some system notes are not part of this API, but are recorded as separate events:
+
+- [Resource label events](resource_label_events.md)
+- [Resource state events](resource_state_events.md)
+- [Resource milestone events](resource_milestone_events.md)
+- [Resource weight events](resource_weight_events.md) **(STARTER)**
## Notes pagination
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index 48c83f1393b..9c7837bc287 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -36,5 +36,5 @@ proxy_set_header X-GitLab-Show-Login-Captcha 1;
In Omnibus GitLab, this can be configured via `/etc/gitlab/gitlab.rb`:
```ruby
-nginx['proxy_set_headers'] = { 'X-GitLab-Show-Login-Captcha' => 1 }
+nginx['proxy_set_headers'] = { 'X-GitLab-Show-Login-Captcha' => '1' }
```
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index d88ca6d7fe3..c2c9341ac02 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -2,8 +2,6 @@
module Gitlab
module Database
- include Gitlab::Metrics::Methods
-
# Minimum PostgreSQL version requirement per documentation:
# https://docs.gitlab.com/ee/install/requirements.html#postgresql-requirements
MINIMUM_POSTGRES_VERSION = 11
@@ -50,10 +48,6 @@ module Gitlab
# It does not include the default public schema
EXTRA_SCHEMAS = [DYNAMIC_PARTITIONS_SCHEMA, STATIC_PARTITIONS_SCHEMA].freeze
- define_histogram :gitlab_database_transaction_seconds do
- docstring "Time spent in database transactions, in seconds"
- end
-
def self.config
ActiveRecord::Base.configurations[Rails.env]
end
@@ -363,8 +357,11 @@ module Gitlab
# observe_transaction_duration is called from ActiveRecordBaseTransactionMetrics.transaction and used to
# record transaction durations.
def self.observe_transaction_duration(duration_seconds)
- labels = Gitlab::Metrics::Transaction.current&.labels || {}
- gitlab_database_transaction_seconds.observe(labels, duration_seconds)
+ if current_transaction = ::Gitlab::Metrics::Transaction.current
+ current_transaction.observe(:gitlab_database_transaction_seconds, duration_seconds) do
+ docstring "Time spent in database transactions, in seconds"
+ end
+ end
rescue Prometheus::Client::LabelSetValidator::LabelSetError => err
# Ensure that errors in recording these metrics don't affect the operation of the application
Rails.logger.error("Unable to observe database transaction duration: #{err}") # rubocop:disable Gitlab/RailsLogger
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index ccf09b37b9b..34289f49677 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -3,7 +3,6 @@
module Gitlab
module Diff
class HighlightCache
- include Gitlab::Metrics::Methods
include Gitlab::Utils::StrongMemoize
EXPIRATION = 1.week
@@ -12,19 +11,6 @@ module Gitlab
delegate :diffable, to: :@diff_collection
delegate :diff_options, to: :@diff_collection
- define_histogram :gitlab_redis_diff_caching_memory_usage_bytes do
- docstring 'Redis diff caching memory usage by key'
- buckets [100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000]
- end
-
- define_counter :gitlab_redis_diff_caching_hit do
- docstring 'Redis diff caching hits'
- end
-
- define_counter :gitlab_redis_diff_caching_miss do
- docstring 'Redis diff caching misses'
- end
-
def initialize(diff_collection)
@diff_collection = diff_collection
end
@@ -117,7 +103,10 @@ module Gitlab
def record_memory_usage(memory_usage)
if memory_usage
- self.class.gitlab_redis_diff_caching_memory_usage_bytes.observe({}, memory_usage)
+ current_transaction&.observe(:gitlab_redis_diff_caching_memory_usage_bytes, memory_usage) do
+ docstring 'Redis diff caching memory usage by key'
+ buckets [100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000]
+ end
end
end
@@ -206,6 +195,10 @@ module Gitlab
#
@diff_collection.raw_diff_files
end
+
+ def current_transaction
+ ::Gitlab::Metrics::Transaction.current
+ end
end
end
end
diff --git a/lib/gitlab/diff/stats_cache.rb b/lib/gitlab/diff/stats_cache.rb
index f38fb21d497..7915d146738 100644
--- a/lib/gitlab/diff/stats_cache.rb
+++ b/lib/gitlab/diff/stats_cache.rb
@@ -3,7 +3,6 @@
module Gitlab
module Diff
class StatsCache
- include Gitlab::Metrics::Methods
include Gitlab::Utils::StrongMemoize
EXPIRATION = 1.week
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 4db0c2bce10..5d91eb605e8 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -5,7 +5,6 @@ module Gitlab
class Blob
include Gitlab::BlobHelper
include Gitlab::EncodingHelper
- include Gitlab::Metrics::Methods
extend Gitlab::Git::WrapsGitalyErrors
# This number is the maximum amount of data that we want to display to
@@ -28,17 +27,21 @@ module Gitlab
attr_accessor :size, :mode, :id, :commit_id, :loaded_size, :binary
attr_writer :name, :path, :data
- define_counter :gitlab_blob_truncated_true do
- docstring 'blob.truncated? == true'
+ def self.gitlab_blob_truncated_true
+ @gitlab_blob_truncated_true ||= ::Gitlab::Metrics.counter(:gitlab_blob_truncated_true, 'blob.truncated? == true')
end
- define_counter :gitlab_blob_truncated_false do
- docstring 'blob.truncated? == false'
+ def self.gitlab_blob_truncated_false
+ @gitlab_blob_truncated_false ||= ::Gitlab::Metrics.counter(:gitlab_blob_truncated_false, 'blob.truncated? == false')
end
- define_histogram :gitlab_blob_size do
- docstring 'Gitlab::Git::Blob size'
- buckets [1_000, 5_000, 10_000, 50_000, 100_000, 500_000, 1_000_000]
+ def self.gitlab_blob_size
+ @gitlab_blob_size ||= ::Gitlab::Metrics.histogram(
+ :gitlab_blob_size,
+ 'Gitlab::Git::Blob size',
+ {},
+ [1_000, 5_000, 10_000, 50_000, 100_000, 500_000, 1_000_000]
+ )
end
class << self
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index b284aadc107..47eda5c741b 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -8,8 +8,6 @@ require 'grpc/health/v1/health_services_pb'
module Gitlab
module GitalyClient
- include Gitlab::Metrics::Methods
-
class TooManyInvocationsError < StandardError
attr_reader :call_site, :invocation_count, :max_call_stack
@@ -191,11 +189,6 @@ module Gitlab
Gitlab::SafeRequestStore[:gitaly_query_time] += duration
end
- def self.current_transaction_labels
- Gitlab::Metrics::Transaction.current&.labels || {}
- end
- private_class_method :current_transaction_labels
-
# For some time related tasks we can't rely on `Time.now` since it will be
# affected by Timecop in some tests, and the clock of some gitaly-related
# components (grpc's c-core and gitaly server) use system time instead of
diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb
index 5fed3d38d7c..7bd55cce363 100644
--- a/lib/gitlab/metrics.rb
+++ b/lib/gitlab/metrics.rb
@@ -3,7 +3,6 @@
module Gitlab
module Metrics
include Gitlab::Metrics::Prometheus
- include Gitlab::Metrics::Methods
EXECUTION_MEASUREMENT_BUCKETS = [0.001, 0.01, 0.1, 1].freeze
@@ -81,25 +80,16 @@ module Gitlab
real_time = (real_stop - real_start)
cpu_time = cpu_stop - cpu_start
- real_duration_seconds = fetch_histogram("gitlab_#{name}_real_duration_seconds".to_sym) do
+ trans.observe("gitlab_#{name}_real_duration_seconds".to_sym, real_time) do
docstring "Measure #{name}"
- base_labels Transaction::BASE_LABELS
buckets EXECUTION_MEASUREMENT_BUCKETS
end
- real_duration_seconds.observe(trans.labels, real_time)
-
- cpu_duration_seconds = fetch_histogram("gitlab_#{name}_cpu_duration_seconds".to_sym) do
+ trans.observe("gitlab_#{name}_cpu_duration_seconds".to_sym, cpu_time) do
docstring "Measure #{name}"
- base_labels Transaction::BASE_LABELS
buckets EXECUTION_MEASUREMENT_BUCKETS
with_feature "prometheus_metrics_measure_#{name}_cpu_duration"
end
- cpu_duration_seconds.observe(trans.labels, cpu_time)
-
- trans.increment("#{name}_real_time", real_time.in_milliseconds, false)
- trans.increment("#{name}_cpu_time", cpu_time.in_milliseconds, false)
- trans.increment("#{name}_call_count", 1, false)
retval
end
diff --git a/lib/gitlab/metrics/elasticsearch_rack_middleware.rb b/lib/gitlab/metrics/elasticsearch_rack_middleware.rb
index 6830eed68d5..5e99fb3c75f 100644
--- a/lib/gitlab/metrics/elasticsearch_rack_middleware.rb
+++ b/lib/gitlab/metrics/elasticsearch_rack_middleware.rb
@@ -8,14 +8,6 @@ module Gitlab
def initialize(app)
@app = app
-
- @requests_total_counter = Gitlab::Metrics.counter(:http_elasticsearch_requests_total,
- 'Amount of calls to Elasticsearch servers during web requests',
- Gitlab::Metrics::Transaction::BASE_LABELS)
- @requests_duration_histogram = Gitlab::Metrics.histogram(:http_elasticsearch_requests_duration_seconds,
- 'Query time for Elasticsearch servers during web requests',
- Gitlab::Metrics::Transaction::BASE_LABELS,
- HISTOGRAM_BUCKETS)
end
def call(env)
@@ -29,12 +21,17 @@ module Gitlab
private
def record_metrics(transaction)
- labels = transaction.labels
query_time = ::Gitlab::Instrumentation::ElasticsearchTransport.query_time
request_count = ::Gitlab::Instrumentation::ElasticsearchTransport.get_request_count
- @requests_total_counter.increment(labels, request_count)
- @requests_duration_histogram.observe(labels, query_time)
+ transaction.increment(:http_elasticsearch_requests_total, request_count) do
+ docstring 'Amount of calls to Elasticsearch servers during web requests'
+ end
+
+ transaction.observe(:http_elasticsearch_requests_duration_seconds, query_time) do
+ docstring 'Query time for Elasticsearch servers during web requests'
+ buckets HISTOGRAM_BUCKETS
+ end
end
end
end
diff --git a/lib/gitlab/metrics/method_call.rb b/lib/gitlab/metrics/method_call.rb
index fbeda3b75e0..c6b0a0c5e76 100644
--- a/lib/gitlab/metrics/method_call.rb
+++ b/lib/gitlab/metrics/method_call.rb
@@ -4,16 +4,7 @@ module Gitlab
module Metrics
# Class for tracking timing information about method calls
class MethodCall
- include Gitlab::Metrics::Methods
- BASE_LABELS = { module: nil, method: nil }.freeze
- attr_reader :real_time, :cpu_time, :call_count, :labels
-
- define_histogram :gitlab_method_call_duration_seconds do
- docstring 'Method calls real duration'
- base_labels Transaction::BASE_LABELS.merge(BASE_LABELS)
- buckets [0.01, 0.05, 0.1, 0.5, 1]
- with_feature :prometheus_metrics_method_instrumentation
- end
+ attr_reader :real_time, :cpu_time, :call_count
# name - The full name of the method (including namespace) such as
# `User#sign_in`.
@@ -42,8 +33,14 @@ module Gitlab
@cpu_time += cpu_time
@call_count += 1
- if above_threshold?
- self.class.gitlab_method_call_duration_seconds.observe(@transaction.labels.merge(labels), real_time)
+ if above_threshold? && transaction
+ label_keys = labels.keys
+ transaction.observe(:gitlab_method_call_duration_seconds, real_time, labels) do
+ docstring 'Method calls real duration'
+ label_keys label_keys
+ buckets [0.01, 0.05, 0.1, 0.5, 1]
+ with_feature :prometheus_metrics_method_instrumentation
+ end
end
retval
@@ -54,6 +51,10 @@ module Gitlab
def above_threshold?
real_time.in_milliseconds >= ::Gitlab::Metrics.method_call_threshold
end
+
+ private
+
+ attr_reader :labels, :transaction
end
end
end
diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb
index 83a7b925392..2b5d1c710f6 100644
--- a/lib/gitlab/metrics/methods.rb
+++ b/lib/gitlab/metrics/methods.rb
@@ -69,62 +69,6 @@ module Gitlab
raise ArgumentError, "uknown metric type #{type}"
end
end
-
- # Fetch and/or initialize counter metric
- # @param [Symbol] name
- # @param [Hash] opts
- def fetch_counter(name, opts = {}, &block)
- fetch_metric(:counter, name, opts, &block)
- end
-
- # Fetch and/or initialize gauge metric
- # @param [Symbol] name
- # @param [Hash] opts
- def fetch_gauge(name, opts = {}, &block)
- fetch_metric(:gauge, name, opts, &block)
- end
-
- # Fetch and/or initialize histogram metric
- # @param [Symbol] name
- # @param [Hash] opts
- def fetch_histogram(name, opts = {}, &block)
- fetch_metric(:histogram, name, opts, &block)
- end
-
- # Fetch and/or initialize summary metric
- # @param [Symbol] name
- # @param [Hash] opts
- def fetch_summary(name, opts = {}, &block)
- fetch_metric(:summary, name, opts, &block)
- end
-
- # Define metric accessor method for a Counter
- # @param [Symbol] name
- # @param [Hash] opts
- def define_counter(name, opts = {}, &block)
- define_metric(:counter, name, opts, &block)
- end
-
- # Define metric accessor method for a Gauge
- # @param [Symbol] name
- # @param [Hash] opts
- def define_gauge(name, opts = {}, &block)
- define_metric(:gauge, name, opts, &block)
- end
-
- # Define metric accessor method for a Histogram
- # @param [Symbol] name
- # @param [Hash] opts
- def define_histogram(name, opts = {}, &block)
- define_metric(:histogram, name, opts, &block)
- end
-
- # Define metric accessor method for a Summary
- # @param [Symbol] name
- # @param [Hash] opts
- def define_summary(name, opts = {}, &block)
- define_metric(:summary, name, opts, &block)
- end
end
end
end
diff --git a/lib/gitlab/metrics/methods/metric_options.rb b/lib/gitlab/metrics/methods/metric_options.rb
index 8e6ceb74c09..1e488df3e99 100644
--- a/lib/gitlab/metrics/methods/metric_options.rb
+++ b/lib/gitlab/metrics/methods/metric_options.rb
@@ -4,14 +4,12 @@ module Gitlab
module Metrics
module Methods
class MetricOptions
- SMALL_NETWORK_BUCKETS = [0.005, 0.01, 0.1, 1, 10].freeze
-
def initialize(options = {})
@multiprocess_mode = options[:multiprocess_mode] || :all
- @buckets = options[:buckets] || SMALL_NETWORK_BUCKETS
- @base_labels = options[:base_labels] || {}
+ @buckets = options[:buckets] || ::Prometheus::Client::Histogram::DEFAULT_BUCKETS
@docstring = options[:docstring]
@with_feature = options[:with_feature]
+ @label_keys = options[:label_keys] || []
end
# Documentation describing metric in metrics endpoint '/-/metrics'
@@ -40,12 +38,21 @@ module Gitlab
end
# Base labels are merged with per metric labels
- def base_labels(base_labels = nil)
- @base_labels = base_labels unless base_labels.nil?
+ def base_labels
+ @base_labels ||= @label_keys.product([nil]).to_h
@base_labels
end
+ def label_keys(label_keys = nil)
+ unless label_keys.nil?
+ @label_keys = label_keys
+ @base_labels = nil
+ end
+
+ @label_keys
+ end
+
# Use feature toggle to control whether certain metric is enabled/disabled
def with_feature(name = nil)
@with_feature = name unless name.nil?
@@ -55,6 +62,7 @@ module Gitlab
def evaluate(&block)
instance_eval(&block) if block_given?
+
self
end
end
diff --git a/lib/gitlab/metrics/rack_middleware.rb b/lib/gitlab/metrics/rack_middleware.rb
index c6a0457ffe5..a6884ea6983 100644
--- a/lib/gitlab/metrics/rack_middleware.rb
+++ b/lib/gitlab/metrics/rack_middleware.rb
@@ -10,8 +10,7 @@ module Gitlab
# env - A Hash containing Rack environment details.
def call(env)
- trans = transaction_from_env(env)
- retval = nil
+ trans = WebTransaction.new(env)
begin
retval = trans.run { @app.call(env) }
@@ -24,21 +23,6 @@ module Gitlab
retval
end
-
- def transaction_from_env(env)
- trans = WebTransaction.new(env)
-
- trans.set(:request_uri, filtered_path(env), false)
- trans.set(:request_method, env['REQUEST_METHOD'], false)
-
- trans
- end
-
- private
-
- def filtered_path(env)
- ActionDispatch::Request.new(env).filtered_path.presence || env['REQUEST_URI']
- end
end
end
end
diff --git a/lib/gitlab/metrics/redis_rack_middleware.rb b/lib/gitlab/metrics/redis_rack_middleware.rb
index f0f99c5f45d..9433355706c 100644
--- a/lib/gitlab/metrics/redis_rack_middleware.rb
+++ b/lib/gitlab/metrics/redis_rack_middleware.rb
@@ -6,14 +6,6 @@ module Gitlab
class RedisRackMiddleware
def initialize(app)
@app = app
-
- @requests_total_counter = Gitlab::Metrics.counter(:http_redis_requests_total,
- 'Amount of calls to Redis servers during web requests',
- Gitlab::Metrics::Transaction::BASE_LABELS)
- @requests_duration_histogram = Gitlab::Metrics.histogram(:http_redis_requests_duration_seconds,
- 'Query time for Redis servers during web requests',
- Gitlab::Metrics::Transaction::BASE_LABELS,
- Gitlab::Instrumentation::Redis::QUERY_TIME_BUCKETS)
end
def call(env)
@@ -27,12 +19,17 @@ module Gitlab
private
def record_metrics(transaction)
- labels = transaction.labels
query_time = Gitlab::Instrumentation::Redis.query_time
request_count = Gitlab::Instrumentation::Redis.get_request_count
- @requests_total_counter.increment(labels, request_count)
- @requests_duration_histogram.observe(labels, query_time)
+ transaction.increment(:http_redis_requests_total, request_count) do
+ docstring 'Amount of calls to Redis servers during web requests'
+ end
+
+ transaction.observe(:http_redis_requests_duration_seconds, query_time) do
+ docstring 'Query time for Redis servers during web requests'
+ buckets Gitlab::Instrumentation::Redis::QUERY_TIME_BUCKETS
+ end
end
end
end
diff --git a/lib/gitlab/metrics/sidekiq_middleware.rb b/lib/gitlab/metrics/sidekiq_middleware.rb
index 1c99e1e730c..8c4e5a8d70c 100644
--- a/lib/gitlab/metrics/sidekiq_middleware.rb
+++ b/lib/gitlab/metrics/sidekiq_middleware.rb
@@ -12,7 +12,9 @@ module Gitlab
begin
# Old gitlad-shell messages don't provide enqueued_at/created_at attributes
enqueued_at = payload['enqueued_at'] || payload['created_at'] || 0
- trans.set(:sidekiq_queue_duration, Time.current.to_f - enqueued_at)
+ trans.set(:gitlab_transaction_sidekiq_queue_duration_total, Time.current.to_f - enqueued_at) do
+ multiprocess_mode :livesum
+ end
trans.run { yield }
rescue Exception => error # rubocop: disable Lint/RescueException
trans.add_event(:sidekiq_exception)
diff --git a/lib/gitlab/metrics/subscribers/action_view.rb b/lib/gitlab/metrics/subscribers/action_view.rb
index 24107e42aa9..e1f1f37c905 100644
--- a/lib/gitlab/metrics/subscribers/action_view.rb
+++ b/lib/gitlab/metrics/subscribers/action_view.rb
@@ -5,14 +5,6 @@ module Gitlab
module Subscribers
# Class for tracking the rendering timings of views.
class ActionView < ActiveSupport::Subscriber
- include Gitlab::Metrics::Methods
- define_histogram :gitlab_view_rendering_duration_seconds do
- docstring 'View rendering time'
- base_labels Transaction::BASE_LABELS.merge({ path: nil })
- buckets [0.001, 0.01, 0.1, 1, 10.0]
- with_feature :prometheus_metrics_view_instrumentation
- end
-
attach_to :action_view
SERIES = 'views'
@@ -27,10 +19,14 @@ module Gitlab
def track(event)
tags = tags_for(event)
+ current_transaction.observe(:gitlab_view_rendering_duration_seconds, event.duration, tags) do
+ docstring 'View rendering time'
+ label_keys %i(view)
+ buckets [0.001, 0.01, 0.1, 1, 10.0]
+ with_feature :prometheus_metrics_view_instrumentation
+ end
- self.class.gitlab_view_rendering_duration_seconds.observe(current_transaction.labels.merge(tags), event.duration)
-
- current_transaction.increment(:view_duration, event.duration)
+ current_transaction.increment(:gitlab_transaction_view_duration_total, event.duration)
end
def relative_path(path)
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
index 2385520c099..43c523cf801 100644
--- a/lib/gitlab/metrics/subscribers/active_record.rb
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -5,7 +5,6 @@ module Gitlab
module Subscribers
# Class for tracking the total query duration of a transaction.
class ActiveRecord < ActiveSupport::Subscriber
- include Gitlab::Metrics::Methods
attach_to :active_record
IGNORABLE_SQL = %w{BEGIN COMMIT}.freeze
@@ -22,7 +21,9 @@ module Gitlab
payload = event.payload
return if payload[:name] == 'SCHEMA' || IGNORABLE_SQL.include?(payload[:sql])
- self.class.gitlab_sql_duration_seconds.observe(current_transaction.labels, event.duration / 1000.0)
+ current_transaction.observe(:gitlab_sql_duration_seconds, event.duration / 1000.0) do
+ buckets [0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0]
+ end
increment_db_counters(payload)
end
@@ -37,12 +38,6 @@ module Gitlab
private
- define_histogram :gitlab_sql_duration_seconds do
- docstring 'SQL time'
- base_labels Transaction::BASE_LABELS
- buckets [0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0]
- end
-
def select_sql_command?(payload)
payload[:sql].match(/\A((?!(.*[^\w'"](DELETE|UPDATE|INSERT INTO)[^\w'"])))(WITH.*)?(SELECT)((?!(FOR UPDATE|FOR SHARE)).)*$/i)
end
@@ -58,7 +53,7 @@ module Gitlab
end
def increment(counter)
- current_transaction.increment(counter, 1)
+ current_transaction.increment("gitlab_transaction_#{counter}_total".to_sym, 1)
if Gitlab::SafeRequestStore.active?
Gitlab::SafeRequestStore[counter] = Gitlab::SafeRequestStore[counter].to_i + 1
diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb
index 2ee7144fe2f..b274d2b1079 100644
--- a/lib/gitlab/metrics/subscribers/rails_cache.rb
+++ b/lib/gitlab/metrics/subscribers/rails_cache.rb
@@ -14,11 +14,10 @@ module Gitlab
return unless current_transaction
return if event.payload[:super_operation] == :fetch
- if event.payload[:hit]
- current_transaction.increment(:cache_read_hit_count, 1, false)
- else
- metric_cache_misses_total.increment(current_transaction.labels)
- current_transaction.increment(:cache_read_miss_count, 1, false)
+ unless event.payload[:hit]
+ current_transaction.increment(:gitlab_cache_misses_total, 1) do
+ docstring 'Cache read miss'
+ end
end
end
@@ -37,25 +36,30 @@ module Gitlab
def cache_fetch_hit(event)
return unless current_transaction
- current_transaction.increment(:cache_read_hit_count, 1)
+ current_transaction.increment(:gitlab_transaction_cache_read_hit_count_total, 1)
end
def cache_generate(event)
return unless current_transaction
- metric_cache_misses_total.increment(current_transaction.labels)
- current_transaction.increment(:cache_read_miss_count, 1)
+ current_transaction.increment(:gitlab_cache_misses_total, 1) do
+ docstring 'Cache read miss'
+ end
+
+ current_transaction.increment(:gitlab_transaction_cache_read_miss_count_total, 1)
end
def observe(key, duration)
return unless current_transaction
- metric_cache_operations_total.increment(current_transaction.labels.merge({ operation: key }))
- metric_cache_operation_duration_seconds.observe({ operation: key }, duration / 1000.0)
- current_transaction.increment(:cache_duration, duration, false)
- current_transaction.increment(:cache_count, 1, false)
- current_transaction.increment("cache_#{key}_duration".to_sym, duration, false)
- current_transaction.increment("cache_#{key}_count".to_sym, 1, false)
+ labels = { operation: key }
+
+ current_transaction.increment(:gitlab_cache_operations_total, 1, labels) do
+ docstring 'Cache operations'
+ label_keys labels.keys
+ end
+
+ metric_cache_operation_duration_seconds.observe(labels, duration / 1000.0)
end
private
@@ -64,14 +68,6 @@ module Gitlab
Transaction.current
end
- def metric_cache_operations_total
- @metric_cache_operations_total ||= ::Gitlab::Metrics.counter(
- :gitlab_cache_operations_total,
- 'Cache operations',
- Transaction::BASE_LABELS
- )
- end
-
def metric_cache_operation_duration_seconds
@metric_cache_operation_duration_seconds ||= ::Gitlab::Metrics.histogram(
:gitlab_cache_operation_duration_seconds,
@@ -80,14 +76,6 @@ module Gitlab
[0.00001, 0.0001, 0.001, 0.01, 0.1, 1.0]
)
end
-
- def metric_cache_misses_total
- @metric_cache_misses_total ||= ::Gitlab::Metrics.counter(
- :gitlab_cache_misses_total,
- 'Cache read miss',
- Transaction::BASE_LABELS
- )
- end
end
end
end
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
index da06be9c79c..fe3bff9e2ed 100644
--- a/lib/gitlab/metrics/transaction.rb
+++ b/lib/gitlab/metrics/transaction.rb
@@ -6,20 +6,36 @@ module Gitlab
class Transaction
include Gitlab::Metrics::Methods
- # base labels shared among all transactions
- BASE_LABELS = { controller: nil, action: nil, feature_category: nil }.freeze
+ # base label keys shared among all transactions
+ BASE_LABEL_KEYS = %i(controller action feature_category).freeze
# labels that potentially contain sensitive information and will be filtered
- FILTERED_LABELS = [:branch, :path].freeze
+ FILTERED_LABEL_KEYS = %i(branch path).freeze
THREAD_KEY = :_gitlab_metrics_transaction
+ SMALL_BUCKETS = [0.1, 0.25, 0.5, 1.0, 2.5, 5.0].freeze
+ BIG_BUCKETS = [100, 1000, 10000, 100000, 1000000, 10000000].freeze
+
# The series to store events (e.g. Git pushes) in.
EVENT_SERIES = 'events'
attr_reader :method
- def self.current
- Thread.current[THREAD_KEY]
+ class << self
+ def current
+ Thread.current[THREAD_KEY]
+ end
+
+ def prometheus_metric(name, type, &block)
+ fetch_metric(type, name) do
+ # set default metric options
+ docstring "#{name.to_s.humanize} #{type}"
+
+ evaluate(&block)
+ # always filter sensitive labels and merge with base ones
+ label_keys BASE_LABEL_KEYS | (label_keys - FILTERED_LABEL_KEYS)
+ end
+ end
end
def initialize
@@ -56,9 +72,15 @@ module Gitlab
@memory_after = System.memory_usage_rss
@finished_at = System.monotonic_time
- self.class.gitlab_transaction_cputime_seconds.observe(labels, thread_cpu_duration)
- self.class.gitlab_transaction_duration_seconds.observe(labels, duration)
- self.class.gitlab_transaction_allocated_memory_bytes.observe(labels, allocated_memory * 1024.0)
+ observe(:gitlab_transaction_cputime_seconds, thread_cpu_duration) do
+ buckets SMALL_BUCKETS
+ end
+ observe(:gitlab_transaction_duration_seconds, duration) do
+ buckets SMALL_BUCKETS
+ end
+ observe(:gitlab_transaction_allocated_memory_bytes, allocated_memory * 1024.0) do
+ buckets BIG_BUCKETS
+ end
Thread.current[THREAD_KEY] = nil
end
@@ -71,8 +93,12 @@ module Gitlab
# event_name - The name of the event (e.g. "git_push").
# tags - A set of tags to attach to the event.
def add_event(event_name, tags = {})
- filtered_tags = filter_tags(tags)
- self.class.transaction_metric(event_name, :counter, prefix: 'event_', tags: filtered_tags).increment(filtered_tags.merge(labels))
+ event_name = "gitlab_transaction_event_#{event_name}_total".to_sym
+ metric = self.class.prometheus_metric(event_name, :counter) do
+ label_keys tags.keys
+ end
+
+ metric.increment(filter_labels(tags))
end
# Returns a MethodCall object for the given name.
@@ -84,52 +110,70 @@ module Gitlab
method
end
- def increment(name, value, use_prometheus = true)
- self.class.transaction_metric(name, :counter).increment(labels, value) if use_prometheus
+ # Increment counter metric
+ #
+ # It will initialize the metric if metric is not found
+ #
+ # block - if provided can be used to initialize metric with custom options (docstring, labels, with_feature)
+ #
+ # Example:
+ # ```
+ # transaction.increment(:mestric_name, 1, { docstring: 'Custom title', base_labels: {sane: 'yes'} } ) do
+ #
+ # transaction.increment(:mestric_name, 1) do
+ # docstring 'Custom title'
+ # label_keys %i(sane)
+ # end
+ # ```
+ def increment(name, value = 1, labels = {}, &block)
+ counter = self.class.prometheus_metric(name, :counter, &block)
+
+ counter.increment(filter_labels(labels), value)
end
- def set(name, value, use_prometheus = true)
- self.class.transaction_metric(name, :gauge).set(labels, value) if use_prometheus
+ # Set gauge metric
+ #
+ # It will initialize the metric if metric is not found
+ #
+ # block - if provided, it can be used to initialize metric with custom options (docstring, labels, with_feature, multiprocess_mode)
+ # - multiprocess_mode is :all by default
+ #
+ # Example:
+ # ```
+ # transaction.set(:mestric_name, 1) do
+ # multiprocess_mode :livesum
+ # end
+ # ```
+ def set(name, value, labels = {}, &block)
+ gauge = self.class.prometheus_metric(name, :gauge, &block)
+
+ gauge.set(filter_labels(labels), value)
+ end
+
+ # Observe histogram metric
+ #
+ # It will initialize the metric if metric is not found
+ #
+ # block - if provided, it can be used to initialize metric with custom options (docstring, labels, with_feature, buckets)
+ #
+ # Example:
+ # ```
+ # transaction.observe(:mestric_name, 1) do
+ # buckets [100, 1000, 10000, 100000, 1000000, 10000000]
+ # end
+ # ```
+ def observe(name, value, labels = {}, &block)
+ histogram = self.class.prometheus_metric(name, :histogram, &block)
+
+ histogram.observe(filter_labels(labels), value)
end
def labels
- BASE_LABELS
+ BASE_LABEL_KEYS.product([nil]).to_h
end
- define_histogram :gitlab_transaction_cputime_seconds do
- docstring 'Transaction thread cputime'
- base_labels BASE_LABELS
- buckets [0.1, 0.25, 0.5, 1.0, 2.5, 5.0]
- end
-
- define_histogram :gitlab_transaction_duration_seconds do
- docstring 'Transaction duration'
- base_labels BASE_LABELS
- buckets [0.1, 0.25, 0.5, 1.0, 2.5, 5.0]
- end
-
- define_histogram :gitlab_transaction_allocated_memory_bytes do
- docstring 'Transaction allocated memory bytes'
- base_labels BASE_LABELS
- buckets [100, 1000, 10000, 100000, 1000000, 10000000]
- end
-
- def self.transaction_metric(name, type, prefix: nil, tags: {})
- metric_name = "gitlab_transaction_#{prefix}#{name}_total".to_sym
- fetch_metric(type, metric_name) do
- docstring "Transaction #{prefix}#{name} #{type}"
- base_labels tags.merge(BASE_LABELS)
-
- if type == :gauge
- multiprocess_mode :livesum
- end
- end
- end
-
- private
-
- def filter_tags(tags)
- tags.without(*FILTERED_LABELS)
+ def filter_labels(labels)
+ labels.empty? ? self.labels : labels.without(*FILTERED_LABEL_KEYS).merge(self.labels)
end
end
end
diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb
index 630788f1a8a..ce1065c0cb3 100644
--- a/lib/gitlab/middleware/rails_queue_duration.rb
+++ b/lib/gitlab/middleware/rails_queue_duration.rb
@@ -19,25 +19,19 @@ module Gitlab
if trans && proxy_start
# Time in milliseconds since gitlab-workhorse started the request
duration = Time.now.to_f * 1_000 - proxy_start.to_f / 1_000_000
- trans.set(:rails_queue_duration, duration)
+ trans.set(:gitlab_transaction_rails_queue_duration_total, duration) do
+ multiprocess_mode :livesum
+ end
duration_s = Gitlab::Utils.ms_to_round_sec(duration)
- metric_rails_queue_duration_seconds.observe(trans.labels, duration_s)
+ trans.observe(:gitlab_rails_queue_duration_seconds, duration_s) do
+ docstring 'Measures latency between GitLab Workhorse forwarding a request to Rails'
+ end
env[GITLAB_RAILS_QUEUE_DURATION_KEY] = duration_s
end
@app.call(env)
end
-
- private
-
- def metric_rails_queue_duration_seconds
- @metric_rails_queue_duration_seconds ||= Gitlab::Metrics.histogram(
- :gitlab_rails_queue_duration_seconds,
- 'Measures latency between GitLab Workhorse forwarding a request to Rails',
- Gitlab::Metrics::Transaction::BASE_LABELS
- )
- end
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 215daddf327..8cd3b49a0d4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16753,6 +16753,9 @@ msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
+msgid "PackageRegistry|Composer"
+msgstr ""
+
msgid "PackageRegistry|Conan"
msgstr ""
@@ -16930,6 +16933,9 @@ msgstr ""
msgid "PackageRegistry|yarn"
msgstr ""
+msgid "PackageType|Composer"
+msgstr ""
+
msgid "PackageType|Conan"
msgstr ""
diff --git a/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb b/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb
new file mode 100644
index 00000000000..20a5910e66d
--- /dev/null
+++ b/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User views diffs file-by-file', :js do
+ let(:merge_request) do
+ create(:merge_request, source_branch: 'squash-large-files', source_project: project, target_project: project)
+ end
+
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user, view_diffs_file_by_file: true) }
+
+ before do
+ allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
+ allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes)
+
+ project.add_developer(user)
+
+ sign_in(user)
+
+ visit(diffs_project_merge_request_path(project, merge_request, anchor: '5091f7b9dd6202e37eaedd73d7b75d82f25fdb61'))
+
+ wait_for_requests
+ end
+
+ it 'shows diffs file-by-file' do
+ page.within('#diffs') do
+ expect(page).not_to have_content('This diff is collapsed')
+
+ click_button 'Next'
+
+ expect(page).not_to have_content('This diff is collapsed')
+ end
+ end
+end
diff --git a/spec/frontend/blob/components/mock_data.js b/spec/frontend/blob/components/mock_data.js
index 58aa1dc6dc9..8cfcec2693c 100644
--- a/spec/frontend/blob/components/mock_data.js
+++ b/spec/frontend/blob/components/mock_data.js
@@ -47,10 +47,12 @@ export const BinaryBlob = {
};
export const RichBlobContentMock = {
+ path: 'foo.md',
richData: '
Rich
',
};
export const SimpleBlobContentMock = {
+ path: 'foo.js',
plainData: 'Plain',
};
diff --git a/spec/frontend/design_management/components/delete_button_spec.js b/spec/frontend/design_management/components/delete_button_spec.js
index 9d3bcd98e44..cd4ef1f0ccd 100644
--- a/spec/frontend/design_management/components/delete_button_spec.js
+++ b/spec/frontend/design_management/components/delete_button_spec.js
@@ -1,11 +1,11 @@
import { shallowMount } from '@vue/test-utils';
-import { GlDeprecatedButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import BatchDeleteButton from '~/design_management/components/delete_button.vue';
describe('Batch delete button component', () => {
let wrapper;
- const findButton = () => wrapper.find(GlDeprecatedButton);
+ const findButton = () => wrapper.find(GlButton);
const findModal = () => wrapper.find(GlModal);
function createComponent(isDeleting = false) {
diff --git a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
index 102e8e0664c..176c10ea584 100644
--- a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
@@ -61,6 +61,10 @@ describe('Design discussions component', () => {
...data,
};
},
+ provide: {
+ projectPath: 'project-path',
+ issueIid: '1',
+ },
mocks: {
$apollo,
$route: {
diff --git a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
index d1341267f8b..830dedc6033 100644
--- a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
+++ b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
@@ -10,7 +10,7 @@ exports[`Design management list item component when item appears in view after i
exports[`Design management list item component with no notes renders item with correct status icon for creation event 1`] = `
diff --git a/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap
index 27c0ba589e6..c4112b46402 100644
--- a/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap
+++ b/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap
@@ -4,16 +4,18 @@ exports[`Design management upload button component renders inverted upload desig
-
Upload designs
-
+
-
Upload designs
@@ -43,7 +47,7 @@ exports[`Design management upload button component renders loading icon 1`] = `
label="Loading"
size="sm"
/>
-
+
-
Upload designs
-
+