summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.markdownlint.yml1
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/blob/components/table_contents.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue2
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue5
-rw-r--r--app/views/projects/blob/_viewer.html.haml1
-rw-r--r--config.ru17
-rw-r--r--config/dependency_decisions.yml7
-rw-r--r--config/initializers/peek.rb6
-rw-r--r--doc/administration/environment_variables.md2
-rw-r--r--doc/administration/logs.md35
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md14
-rw-r--r--doc/administration/operations/index.md1
-rw-r--r--doc/administration/operations/unicorn.md115
-rw-r--r--doc/development/architecture.md17
-rw-r--r--doc/development/usage_ping/metrics_dictionary.md12
-rw-r--r--doc/user/gitlab_com/index.md14
-rw-r--r--lib/peek/views/memory.rb76
-rw-r--r--locale/gitlab.pot135
-rw-r--r--package.json4
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper.js11
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper_spec.js3
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js11
-rw-r--r--spec/frontend/notes/components/discussion_reply_placeholder_spec.js23
-rw-r--r--spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap2
-rw-r--r--spec/lib/peek/views/memory_spec.rb53
-rw-r--r--yarn.lock16
29 files changed, 272 insertions, 320 deletions
diff --git a/.markdownlint.yml b/.markdownlint.yml
index 4e852880d26..dd04406f68d 100644
--- a/.markdownlint.yml
+++ b/.markdownlint.yml
@@ -130,7 +130,6 @@
"Ubuntu",
"Ultra Auth",
"Unicorn",
- "unicorn-worker-killer",
"URL",
"WebdriverIO",
"YAML",
diff --git a/Gemfile b/Gemfile
index 018bf5fbcbe..25fb430c290 100644
--- a/Gemfile
+++ b/Gemfile
@@ -185,7 +185,6 @@ gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base'
group :unicorn do
gem 'unicorn', '~> 5.5'
- gem 'unicorn-worker-killer', '~> 0.4.4'
end
group :puma do
diff --git a/Gemfile.lock b/Gemfile.lock
index c70f1710d50..62f5eb4d3a9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1318,9 +1318,6 @@ GEM
unicorn (5.5.5)
kgio (~> 2.6)
raindrops (~> 0.7)
- unicorn-worker-killer (0.4.4)
- get_process_mem (~> 0)
- unicorn (>= 4, < 6)
uniform_notifier (1.13.0)
unleash (0.1.5)
murmurhash3 (~> 0.1.6)
@@ -1653,7 +1650,6 @@ DEPENDENCIES
u2f (~> 0.2.1)
unf (~> 0.1.4)
unicorn (~> 5.5)
- unicorn-worker-killer (~> 0.4.4)
unleash (~> 0.1.5)
valid_email (~> 0.1)
validates_hostname (~> 1.0.11)
diff --git a/app/assets/javascripts/blob/components/table_contents.vue b/app/assets/javascripts/blob/components/table_contents.vue
index 3a0a385d494..78ecb82f2cd 100644
--- a/app/assets/javascripts/blob/components/table_contents.vue
+++ b/app/assets/javascripts/blob/components/table_contents.vue
@@ -60,7 +60,7 @@ export default {
</script>
<template>
- <gl-dropdown v-if="!isHidden && items.length" icon="list-bulleted" class="gl-mr-2">
+ <gl-dropdown v-if="!isHidden && items.length" icon="list-bulleted" class="gl-mr-2" lazy>
<gl-dropdown-item v-for="(item, index) in items" :key="index" :href="`#${item.anchor}`">
<span
:style="{ 'padding-left': `${item.spacing}px` }"
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue b/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
index fe56833016e..8ddf50cb357 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate_deprecated.vue
@@ -10,7 +10,7 @@ export default {
},
props: {
estimate: {
- type: Number,
+ type: [Number, String],
required: true,
},
},
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index ebe9c4eee2f..1bb847217d1 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -74,6 +74,11 @@ export default {
keys: ['label', 'code', 'proxy', 'error'],
},
{
+ metric: 'memory',
+ header: s__('PerformanceBar|Memory'),
+ keys: ['item_header', 'item_content'],
+ },
+ {
metric: 'total',
header: s__('PerformanceBar|Frontend resources'),
keys: ['name', 'size'],
diff --git a/app/views/projects/blob/_viewer.html.haml b/app/views/projects/blob/_viewer.html.haml
index a0d82ffd2c7..8713ce79d96 100644
--- a/app/views/projects/blob/_viewer.html.haml
+++ b/app/views/projects/blob/_viewer.html.haml
@@ -5,6 +5,7 @@
- external_embed = local_assigns.fetch(:external_embed, false)
- viewer_url = local_assigns.fetch(:viewer_url) { url_for(safe_params.merge(viewer: viewer.type, format: :json)) } if load_async
+- add_page_startup_api_call viewer_url
.blob-viewer{ data: { type: viewer.type, rich_type: rich_type, url: viewer_url, path: viewer.blob.path }, class: ('hidden' if hidden) }
- if render_error
= render 'projects/blob/render_error', viewer: viewer
diff --git a/config.ru b/config.ru
index 0c50b3fdf6f..ed76239ef2e 100644
--- a/config.ru
+++ b/config.ru
@@ -2,25 +2,10 @@
# This file is used by Rack-based servers to start the application.
-if defined?(Unicorn)
- require 'unicorn'
-
- if ENV['RAILS_ENV'] == 'production' || ENV['RAILS_ENV'] == 'staging'
- # Unicorn self-process killer
- require 'unicorn/worker_killer'
-
- min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 400 * 1 << 20).to_i
- max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 650 * 1 << 20).to_i
-
- # Max memory size (RSS) per worker
- use Unicorn::WorkerKiller::Oom, min, max
- end
-end
-
require ::File.expand_path('../config/environment', __FILE__)
def master_process?
- Prometheus::PidProvider.worker_id.in? %w(unicorn_master puma_master)
+ Prometheus::PidProvider.worker_id == 'puma_master'
end
warmup do |app|
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 774254d2ff1..d76dd8fe25b 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -131,13 +131,6 @@
:versions: []
:when: 2016-05-02 05:45:28.817510000 Z
- - :license
- - unicorn-worker-killer
- - ruby
- - :who: Connor Shea
- :why: https://github.com/kzk/unicorn-worker-killer/blob/master/LICENSE
- :versions: []
- :when: 2016-05-02 05:45:38.323867000 Z
-- - :license
- unf
- BSD
- :who: Connor Shea
diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb
index 85bfc4f0214..6fd92865731 100644
--- a/config/initializers/peek.rb
+++ b/config/initializers/peek.rb
@@ -15,9 +15,15 @@ Peek.into Peek::Views::Elasticsearch
Peek.into Peek::Views::Rugged
Peek.into Peek::Views::ExternalHttp
Peek.into Peek::Views::BulletDetailed if defined?(Bullet)
+Peek.into Peek::Views::Memory
Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled?
+# Trigger view creation here, since views might be subscribing to Rails notifications
+# via setup_subscribers, which is called in the initializer.
+# See https://github.com/peek/peek/blob/master/lib/peek/views/view.rb
+Peek.views
+
ActiveSupport::Notifications.subscribe('endpoint_run.grape') do |_name, _start, _finish, _id, payload|
if request_id = payload[:env]['action_dispatch.request_id']
Peek.adapter.save(request_id)
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index a168584e754..f98cddb52c9 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -32,8 +32,6 @@ You can use the following environment variables to override certain values:
| `GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`). |
| `GITLAB_ROOT_PASSWORD` | string | Sets the password for the `root` user on installation. |
| `GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` | string | Sets the initial registration token used for runners. |
-| `GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
-| `GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the [unicorn-worker-killer](operations/unicorn.md#unicorn-worker-killer). |
| `RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging`, or `test`. |
| `UNSTRUCTURED_RAILS_LOG` | string | Enables the unstructured log in addition to JSON logs (defaults to `true`). |
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 8894f46aa26..5921406973b 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -611,41 +611,6 @@ This file lives in `/var/log/gitlab/puma/puma_stderr.log` for
Omnibus GitLab packages, or in `/home/git/gitlab/log/puma_stderr.log` for
installations from source.
-## Unicorn Logs
-
-Starting with GitLab 13.0, Puma is the default web server used in GitLab
-all-in-one package based installations, and GitLab Helm chart deployments.
-
-### `unicorn_stdout.log`
-
-This file lives in `/var/log/gitlab/unicorn/unicorn_stdout.log` for
-Omnibus GitLab packages or in `/home/git/gitlab/log/unicorn_stdout.log` for
-for installations from source.
-
-### `unicorn_stderr.log`
-
-This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for
-Omnibus GitLab packages or in `/home/git/gitlab/log/unicorn_stderr.log` for
-for installations from source.
-
-These logs contain all information about the state of Unicorn processes at any given time.
-
-```plaintext
-I, [2015-02-13T06:14:46.680381 #9047] INFO -- : Refreshing Gem list
-I, [2015-02-13T06:14:56.931002 #9047] INFO -- : listening on addr=127.0.0.1:8080 fd=12
-I, [2015-02-13T06:14:56.931381 #9047] INFO -- : listening on addr=/var/opt/gitlab/gitlab-rails/sockets/gitlab.socket fd=13
-I, [2015-02-13T06:14:56.936638 #9047] INFO -- : master process ready
-I, [2015-02-13T06:14:56.946504 #9092] INFO -- : worker=0 spawned pid=9092
-I, [2015-02-13T06:14:56.946943 #9092] INFO -- : worker=0 ready
-I, [2015-02-13T06:14:56.947892 #9094] INFO -- : worker=1 spawned pid=9094
-I, [2015-02-13T06:14:56.948181 #9094] INFO -- : worker=1 ready
-W, [2015-02-13T07:16:01.312916 #9094] WARN -- : #<Unicorn::HttpServer:0x0000000208f618>: worker (pid: 9094) exceeds memory limit (320626688 bytes > 247066940 bytes)
-W, [2015-02-13T07:16:01.313000 #9094] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 9094) alive: 3621 sec (trial 1)
-I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped #<Process::Status: pid 9094 exit 0> worker=1
-I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379
-I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready
-```
-
## `repocheck.log`
This file lives in `/var/log/gitlab/gitlab-rails/repocheck.log` for
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 72ab536ceae..780e5b47fba 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Performance Bar **(FREE SELF)**
-> The **Stats** field [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271551) in GitLab SaaS 13.9.
+> The **Stats** field [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271551) in GitLab 13.9.
+> The **Memory** field [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330736) in GitLab 14.0.
You can display the GitLab Performance Bar to see statistics for the performance
of a page. When activated, it looks as follows:
@@ -40,9 +41,11 @@ From left to right, it displays:
Time until something was visible to the user.
- [**DomContentLoaded**](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp) Event.
- **Total number of requests** the page loaded.
-- **Trace**: If Jaeger is integrated, **Trace** links to a Jaeger tracing page
+- **Memory**: the amount of memory consumed and objects allocated during the selected request.
+ Select it to display a window with more details.
+- **Trace**: if Jaeger is integrated, **Trace** links to a Jaeger tracing page
with the current request's `correlation_id` included.
-- **+**: A link to add a request's details to the performance bar. The request
+- **+**: a link to add a request's details to the performance bar. The request
can be added by its full URL (authenticated as the current user), or by the value of
its `X-Request-Id` header.
- **Download**: a link to download the raw JSON used to generate the Performance Bar reports.
@@ -52,6 +55,11 @@ From left to right, it displays:
- **Stats** (optional): if the `GITLAB_PERFORMANCE_BAR_STATS_URL` environment variable is set,
this URL is displayed in the bar. In GitLab 13.9 and later, used only in GitLab SaaS.
+NOTE:
+Not all indicators are available in all environments. For instance, the memory view
+requires to run Ruby with [specific patches](https://gitlab.com/gitlab-org/gitlab-build-images/-/blob/master/patches/ruby/2.7.2/thread-memory-allocations-2.7.patch) applied.
+When running GitLab locally using the GDK this is typically not the case and the memory view cannot be used.
+
## Request warnings
Requests that exceed predefined limits display a warning **{warning}** icon and
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index 708861d8529..268c9281d87 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -22,7 +22,6 @@ Keep your GitLab instance up and running smoothly.
to restart Sidekiq.
- [Multiple Sidekiq processes](extra_sidekiq_processes.md): Configure multiple Sidekiq processes to ensure certain queues always have dedicated workers, no matter the number of jobs that need to be processed. **(FREE SELF)**
- [Puma](puma.md): Understand Puma and puma-worker-killer.
-- [Unicorn](unicorn.md): Understand Unicorn and unicorn-worker-killer.
- Speed up SSH operations by [Authorizing SSH users via a fast,
indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or
by [doing away with user SSH keys stored on GitLab entirely in favor
diff --git a/doc/administration/operations/unicorn.md b/doc/administration/operations/unicorn.md
deleted file mode 100644
index 03995ee05ba..00000000000
--- a/doc/administration/operations/unicorn.md
+++ /dev/null
@@ -1,115 +0,0 @@
----
-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/#assignments
----
-
-# Understanding Unicorn and unicorn-worker-killer
-
-NOTE:
-Starting with GitLab 13.0, Puma is the default web server used in GitLab
-all-in-one package based installations as well as GitLab Helm chart deployments.
-
-## Unicorn
-
-GitLab uses [Unicorn](https://yhbt.net/unicorn/), a pre-forking Ruby web
-server, to handle web requests (web browsers and Git HTTP clients). Unicorn is
-a daemon written in Ruby and C that can load and run a Ruby on Rails
-application; in our case the Rails application is GitLab Community Edition or
-GitLab Enterprise Edition.
-
-Unicorn has a multi-process architecture to make better use of available CPU
-cores (processes can run on different cores) and to have stronger fault
-tolerance (most failures stay isolated in only one process and cannot take down
-GitLab entirely). On startup, the Unicorn 'master' process loads a clean Ruby
-environment with the GitLab application code, and then spawns 'workers' which
-inherit this clean initial environment. The 'master' never handles any
-requests, that is left to the workers. The operating system network stack
-queues incoming requests and distributes them among the workers.
-
-In a perfect world, the master would spawn its pool of workers once, and then
-the workers handle incoming web requests one after another until the end of
-time. In reality, worker processes can crash or time out: if the master notices
-that a worker takes too long to handle a request it will terminate the worker
-process with SIGKILL ('kill -9'). No matter how the worker process ended, the
-master process will replace it with a new 'clean' process again. Unicorn is
-designed to be able to replace 'crashed' workers without dropping user
-requests.
-
-This is what a Unicorn worker timeout looks like in `unicorn_stderr.log`. The
-master process has PID 56227 below.
-
-```plaintext
-[2015-06-05T10:58:08.660325 #56227] ERROR -- : worker=10 PID:53009 timeout (61s > 60s), killing
-[2015-06-05T10:58:08.699360 #56227] ERROR -- : reaped #<Process::Status: pid 53009 SIGKILL (signal 9)> worker=10
-[2015-06-05T10:58:08.708141 #62538] INFO -- : worker=10 spawned pid=62538
-[2015-06-05T10:58:08.708824 #62538] INFO -- : worker=10 ready
-```
-
-### Tunable options
-
-The main tunable options for Unicorn are the number of worker processes and the
-request timeout after which the Unicorn master terminates a worker process.
-See the [Omnibus GitLab Unicorn settings
-documentation](https://docs.gitlab.com/omnibus/settings/unicorn.html)
-if you want to adjust these settings.
-
-## unicorn-worker-killer
-
-GitLab has memory leaks. These memory leaks manifest themselves in long-running
-processes, such as Unicorn workers. (The Unicorn master process is not known to
-leak memory, probably because it does not handle user requests.)
-
-To make these memory leaks manageable, GitLab comes with the
-[unicorn-worker-killer gem](https://github.com/kzk/unicorn-worker-killer). This
-gem [monkey-patches](https://en.wikipedia.org/wiki/Monkey_patch) the Unicorn
-workers to do a memory self-check after every 16 requests. If the memory of the
-Unicorn worker exceeds a pre-set limit then the worker process exits. The
-Unicorn master then automatically replaces the worker process.
-
-This is a robust way to handle memory leaks: Unicorn is designed to handle
-workers that 'crash' so no user requests will be dropped. The
-unicorn-worker-killer gem is designed to only terminate a worker process _in
-between requests_, so no user requests are affected. You can set the minimum and
-maximum memory threshold (in bytes) for the Unicorn worker killer by
-setting the following values `/etc/gitlab/gitlab.rb`:
-
-- For GitLab **12.7** and newer:
-
- ```ruby
- unicorn['worker_memory_limit_min'] = "1024 * 1 << 20"
- unicorn['worker_memory_limit_max'] = "1280 * 1 << 20"
- ```
-
-- For GitLab **12.6** and older:
-
- ```ruby
- unicorn['worker_memory_limit_min'] = "400 * 1 << 20"
- unicorn['worker_memory_limit_max'] = "650 * 1 << 20"
- ```
-
-Otherwise, you can set the `GITLAB_UNICORN_MEMORY_MIN` and `GITLAB_UNICORN_MEMORY_MAX`
-[environment variables](../environment_variables.md).
-
-This is what a Unicorn worker memory restart looks like in unicorn_stderr.log.
-You see that worker 4 (PID 125918) is inspecting itself and decides to exit.
-The threshold memory value was 254802235 bytes, about 250MB. With GitLab this
-threshold is a random value between 200 and 250 MB. The master process (PID
-117565) then reaps the worker process and spawns a new 'worker 4' with PID
-127549.
-
-```plaintext
-[2015-06-05T12:07:41.828374 #125918] WARN -- : #<Unicorn::HttpServer:0x00000002734770>: worker (pid: 125918) exceeds memory limit (256413696 bytes > 254802235 bytes)
-[2015-06-05T12:07:41.828472 #125918] WARN -- : Unicorn::WorkerKiller send SIGQUIT (pid: 125918) alive: 23 sec (trial 1)
-[2015-06-05T12:07:42.025916 #117565] INFO -- : reaped #<Process::Status: pid 125918 exit 0> worker=4
-[2015-06-05T12:07:42.034527 #127549] INFO -- : worker=4 spawned pid=127549
-[2015-06-05T12:07:42.035217 #127549] INFO -- : worker=4 ready
-```
-
-One other thing that stands out in the log snippet above, taken from
-GitLab.com, is that 'worker 4' was serving requests for only 23 seconds. This
-is a normal value for our current GitLab.com setup and traffic.
-
-The high frequency of Unicorn memory restarts on some GitLab sites can be a
-source of confusion for administrators. Usually they are a [red
-herring](https://en.wikipedia.org/wiki/Red_herring).
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index fdcaa91a639..d8d452240ff 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -710,23 +710,6 @@ disabled by default.
[Puma](https://puma.io/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often this displays in process output as `bundle` or `config.ru` depending on the GitLab version.
-#### Unicorn
-
-Starting with GitLab 13.0, Puma is the default web server and Unicorn has been
-disabled by default.
-
-- [Project page](https://gitlab.com/gitlab-org/gitlab/blob/master/README.md)
-- Configuration:
- - [Omnibus](https://docs.gitlab.com/omnibus/settings/unicorn.html)
- - [Charts](https://docs.gitlab.com/charts/charts/gitlab/webservice/)
- - [Source](../install/installation.md#configure-it)
- - [GDK](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example)
-- Layer: Core Service (Processor)
-- Process: `unicorn`
-- GitLab.com: [Unicorn](../user/gitlab_com/index.md#unicorn)
-
-[Unicorn](https://yhbt.net/unicorn/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often this displays in process output as `bundle` or `config.ru` depending on the GitLab version.
-
#### LDAP Authentication
- Configuration:
diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md
index 9fd09714e65..c888a9858a6 100644
--- a/doc/development/usage_ping/metrics_dictionary.md
+++ b/doc/development/usage_ping/metrics_dictionary.md
@@ -57,6 +57,18 @@ Metric definitions can have one of the following statuses:
- `deprecated`: Metric is deprecated and possibly planned to be removed.
- `removed`: Metric was removed, but it may appear in Usage Ping payloads sent from instances running on older versions of GitLab.
+### Metric value_type
+
+Metric definitions can have one of the following values for `value_type`:
+
+- `boolean`
+- `number`
+- `string`
+- `object`: A metric with `value_type: object` must have `value_json_schema` with a link to the JSON schema for the object.
+In general, we avoid complex objects and prefer one of the `boolean`, `number`, or `string` value types.
+An example of a metric that uses `value_type: object` is `topology` (`/config/metrics/settings/20210323120839_topology.yml`),
+which has a related schema in `/config/metrics/objects_schemas/topology_schema.json`.
+
### Metric name
To improve metric discoverability by a wider audience, each metric with
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index cdb4ca52c9c..f05e5f00bc2 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -508,20 +508,6 @@ of proposed changes can be found at
GitLab.com uses the default of 60 seconds for [Puma request timeouts](https://docs.gitlab.com/omnibus/settings/puma.html#worker-timeout).
-## Unicorn
-
-GitLab.com adjusts the memory limits for the [unicorn-worker-killer](https://rubygems.org/gems/unicorn-worker-killer) gem.
-
-Base default:
-
-- `memory_limit_min` = 750MiB
-- `memory_limit_max` = 1024MiB
-
-Web front-ends:
-
-- `memory_limit_min` = 1024MiB
-- `memory_limit_max` = 1280MiB
-
## GitLab.com-specific rate limits
NOTE:
diff --git a/lib/peek/views/memory.rb b/lib/peek/views/memory.rb
new file mode 100644
index 00000000000..399474dedf1
--- /dev/null
+++ b/lib/peek/views/memory.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module Peek
+ module Views
+ class Memory < View
+ MEM_TOTAL_LABEL = 'Total'
+ MEM_OBJECTS_LABEL = 'Objects allocated'
+ MEM_MALLOCS_LABEL = 'Allocator calls'
+ MEM_BYTES_LABEL = 'Large allocations'
+
+ def initialize(options = {})
+ super
+
+ @thread_memory = {}
+ end
+
+ def results
+ return thread_memory if thread_memory.empty?
+
+ {
+ calls: byte_string(thread_memory[:mem_total_bytes]),
+ summary: {
+ MEM_OBJECTS_LABEL => number_string(thread_memory[:mem_objects]),
+ MEM_MALLOCS_LABEL => number_string(thread_memory[:mem_mallocs]),
+ MEM_BYTES_LABEL => byte_string(thread_memory[:mem_bytes])
+ },
+ details: [
+ {
+ item_header: MEM_TOTAL_LABEL,
+ item_content: "Total memory use of this request. This includes both occupancy of existing heap slots " \
+ "as well as newly allocated memory due to large objects. Not adjusted for freed memory. " \
+ "Lower is better."
+ },
+ {
+ item_header: MEM_OBJECTS_LABEL,
+ item_content: "Total number of objects allocated by the Ruby VM during this request. " \
+ "Not adjusted for objects that were freed again. Lower is better."
+ },
+ {
+ item_header: MEM_MALLOCS_LABEL,
+ item_content: "Total number of times Ruby had to call `malloc`, the C memory allocator. " \
+ "This is necessary for objects that are too large to fit into a 40 Byte slot in Ruby's managed heap. " \
+ "Lower is better."
+ },
+ {
+ item_header: MEM_BYTES_LABEL,
+ item_content: "Memory allocated for objects that did not fit into a heap slot. " \
+ "Not adjusted for memory that was freed again. Lower is better."
+ }
+ ]
+ }
+ end
+
+ private
+
+ attr_reader :thread_memory
+
+ def setup_subscribers
+ subscribe 'process_action.action_controller' do
+ # Ensure that Peek will see memory instrumentation in `results` by triggering it when
+ # a request is done processing. Peek itself hooks into the same notification:
+ # https://github.com/peek/peek/blob/master/lib/peek/railtie.rb
+ Gitlab::InstrumentationHelper.instrument_thread_memory_allocations(thread_memory)
+ end
+ end
+
+ def byte_string(bytes)
+ ActiveSupport::NumberHelper.number_to_human_size(bytes)
+ end
+
+ def number_string(num)
+ ActiveSupport::NumberHelper.number_to_human(num, units: { thousand: 'k', million: 'M', billion: 'B' })
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c3ca3be623f..aadde55bfe4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6778,72 +6778,6 @@ msgstr ""
msgid "Cloud licenses can not be removed."
msgstr ""
-msgid "CloudLicense|Activate"
-msgstr ""
-
-msgid "CloudLicense|Activate subscription"
-msgstr ""
-
-msgid "CloudLicense|Activation code"
-msgstr ""
-
-msgid "CloudLicense|Billable users"
-msgstr ""
-
-msgid "CloudLicense|Buy subscription"
-msgstr ""
-
-msgid "CloudLicense|Enter activation code"
-msgstr ""
-
-msgid "CloudLicense|Free trial"
-msgstr ""
-
-msgid "CloudLicense|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
-msgstr ""
-
-msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
-msgstr ""
-
-msgid "CloudLicense|Maximum users"
-msgstr ""
-
-msgid "CloudLicense|Paste your activation code"
-msgstr ""
-
-msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
-
-msgid "CloudLicense|Start free trial"
-msgstr ""
-
-msgid "CloudLicense|Subscription"
-msgstr ""
-
-msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
-msgstr ""
-
-msgid "CloudLicense|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
-msgstr ""
-
-msgid "CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription."
-msgstr ""
-
-msgid "CloudLicense|Users in subscription"
-msgstr ""
-
-msgid "CloudLicense|Users over subscription"
-msgstr ""
-
-msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
-msgstr ""
-
-msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
-
-msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -23973,6 +23907,9 @@ msgstr ""
msgid "PerformanceBar|Gitaly calls"
msgstr ""
+msgid "PerformanceBar|Memory"
+msgstr ""
+
msgid "PerformanceBar|Redis calls"
msgstr ""
@@ -31606,15 +31543,42 @@ msgstr ""
msgid "Sunday"
msgstr ""
+msgid "SuperSonics|Activate"
+msgstr ""
+
+msgid "SuperSonics|Activate subscription"
+msgstr ""
+
msgid "SuperSonics|Activated on"
msgstr ""
+msgid "SuperSonics|Activation code"
+msgstr ""
+
msgid "SuperSonics|An error occurred while activating your subscription."
msgstr ""
+msgid "SuperSonics|Billable users"
+msgstr ""
+
+msgid "SuperSonics|Buy subscription"
+msgstr ""
+
+msgid "SuperSonics|Enter activation code"
+msgstr ""
+
msgid "SuperSonics|Expires on"
msgstr ""
+msgid "SuperSonics|Free trial"
+msgstr ""
+
+msgid "SuperSonics|Get help for the most common connectivity issues by %{linkStart}troubleshooting the activation code%{linkEnd}."
+msgstr ""
+
+msgid "SuperSonics|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
+msgstr ""
+
msgid "SuperSonics|ID"
msgstr ""
@@ -31630,18 +31594,33 @@ msgstr ""
msgid "SuperSonics|Manage"
msgstr ""
+msgid "SuperSonics|Maximum users"
+msgstr ""
+
+msgid "SuperSonics|Paste your activation code"
+msgstr ""
+
msgid "SuperSonics|Plan"
msgstr ""
+msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
+msgstr ""
+
msgid "SuperSonics|Renews"
msgstr ""
msgid "SuperSonics|Seats"
msgstr ""
+msgid "SuperSonics|Start free trial"
+msgstr ""
+
msgid "SuperSonics|Started"
msgstr ""
+msgid "SuperSonics|Subscription"
+msgstr ""
+
msgid "SuperSonics|Subscription details"
msgstr ""
@@ -31657,21 +31636,45 @@ msgstr ""
msgid "SuperSonics|This field is required."
msgstr ""
+msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "SuperSonics|This is the number of %{billableUsersLinkStart}billable users%{billableUsersLinkEnd} on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "SuperSonics|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Licensing%{linkEnd} service, a hassle-free way to manage your subscription."
+msgstr ""
+
msgid "SuperSonics|Type"
msgstr ""
msgid "SuperSonics|Upload a legacy license"
msgstr ""
+msgid "SuperSonics|Users in subscription"
+msgstr ""
+
+msgid "SuperSonics|Users over subscription"
+msgstr ""
+
+msgid "SuperSonics|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "SuperSonics|Valid From"
msgstr ""
msgid "SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}."
msgstr ""
+msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
+msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "SuperSonics|Your subscription"
msgstr ""
diff --git a/package.json b/package.json
index e5431b98689..2c2816edc98 100644
--- a/package.json
+++ b/package.json
@@ -101,7 +101,7 @@
"codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^6.4.1",
- "core-js": "^3.12.1",
+ "core-js": "^3.13.0",
"cron-validator": "^1.1.1",
"cropper": "^2.3.0",
"css-loader": "^2.1.1",
@@ -193,7 +193,7 @@
"@gitlab/eslint-plugin": "8.4.0",
"@gitlab/stylelint-config": "2.3.0",
"@testing-library/dom": "^7.16.2",
- "@vue/test-utils": "1.1.2",
+ "@vue/test-utils": "1.2.0",
"acorn": "^6.3.0",
"axios-mock-adapter": "^1.15.0",
"babel-jest": "^26.5.2",
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper.js b/spec/frontend/__helpers__/vue_test_utils_helper.js
index a94cee84f74..2aae91f8a39 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper.js
@@ -1,5 +1,5 @@
import * as testingLibrary from '@testing-library/dom';
-import { createWrapper, WrapperArray, mount, shallowMount } from '@vue/test-utils';
+import { createWrapper, WrapperArray, ErrorWrapper, mount, shallowMount } from '@vue/test-utils';
import { isArray, upperFirst } from 'lodash';
const vNodeContainsText = (vnode, text) =>
@@ -81,14 +81,9 @@ export const extendedWrapper = (wrapper) => {
options,
);
- // Return VTU `ErrorWrapper` if element is not found
- // https://github.com/vuejs/vue-test-utils/blob/dev/packages/test-utils/src/error-wrapper.js
- // VTU does not expose `ErrorWrapper` so, as of now, this is the best way to
- // create an `ErrorWrapper`
+ // Element not found, return an `ErrorWrapper`
if (!elements.length) {
- const emptyElement = document.createElement('div');
-
- return createWrapper(emptyElement).find('testing-library-element-not-found');
+ return new ErrorWrapper(query);
}
return createWrapper(elements[0], this.options || {});
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
index dfe5a483223..3bb228f94b8 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
@@ -4,6 +4,7 @@ import {
shallowMount,
Wrapper as VTUWrapper,
WrapperArray as VTUWrapperArray,
+ ErrorWrapper as VTUErrorWrapper,
} from '@vue/test-utils';
import {
extendedWrapper,
@@ -195,7 +196,7 @@ describe('Vue test utils helpers', () => {
});
it('returns a VTU error wrapper', () => {
- expect(wrapper[findMethod](text, options).exists()).toBe(false);
+ expect(wrapper[findMethod](text, options)).toBeInstanceOf(VTUErrorWrapper);
});
});
});
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 646e51160d8..41a93c7ba5a 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -656,7 +656,7 @@ describe('RepoEditor', () => {
});
it("does not add file to state or set markdown image syntax if the file isn't markdown", async () => {
- wrapper.setProps({
+ await wrapper.setProps({
file: setFileName('myfile.txt'),
});
pasteImage();
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index c6a7d7ead98..925dbcc09ec 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -20,7 +20,7 @@ const createUnallowedNote = () =>
describe('DiscussionActions', () => {
let wrapper;
- const createComponentFactory = (shallow = true) => (props) => {
+ const createComponentFactory = (shallow = true) => (props, options) => {
const store = createStore();
const mountFn = shallow ? shallowMount : mount;
@@ -34,6 +34,7 @@ describe('DiscussionActions', () => {
shouldShowJumpToNextDiscussion: true,
...props,
},
+ ...options,
});
};
@@ -90,17 +91,17 @@ describe('DiscussionActions', () => {
describe('events handling', () => {
const createComponent = createComponentFactory(false);
- beforeEach(() => {
- createComponent();
- });
-
it('emits showReplyForm event when clicking on reply placeholder', () => {
+ createComponent({}, { attachTo: document.body });
+
jest.spyOn(wrapper.vm, '$emit');
wrapper.find(ReplyPlaceholder).find('textarea').trigger('focus');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm');
});
it('emits resolve event when clicking on resolve button', () => {
+ createComponent();
+
jest.spyOn(wrapper.vm, '$emit');
wrapper.find(ResolveDiscussionButton).find('button').trigger('click');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve');
diff --git a/spec/frontend/notes/components/discussion_reply_placeholder_spec.js b/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
index 2a4cd0df0c7..3932f818c4e 100644
--- a/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
+++ b/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
@@ -6,31 +6,34 @@ const placeholderText = 'Test Button Text';
describe('ReplyPlaceholder', () => {
let wrapper;
- const findTextarea = () => wrapper.find({ ref: 'textarea' });
-
- beforeEach(() => {
+ const createComponent = ({ options = {} } = {}) => {
wrapper = shallowMount(ReplyPlaceholder, {
propsData: {
placeholderText,
},
+ ...options,
});
- });
+ };
+
+ const findTextarea = () => wrapper.find({ ref: 'textarea' });
afterEach(() => {
wrapper.destroy();
});
- it('emits focus event on button click', () => {
- findTextarea().trigger('focus');
+ it('emits focus event on button click', async () => {
+ createComponent({ options: { attachTo: document.body } });
+
+ await findTextarea().trigger('focus');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted()).toEqual({
- focus: [[]],
- });
+ expect(wrapper.emitted()).toEqual({
+ focus: [[]],
});
});
it('should render reply button', () => {
+ createComponent();
+
expect(findTextarea().attributes('placeholder')).toEqual(placeholderText);
});
});
diff --git a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
index c4c48ea7517..4ba9120d196 100644
--- a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
+++ b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
@@ -66,7 +66,7 @@ exports[`Code Coverage when fetching data is successful matches the snapshot 1`]
<gl-area-chart-stub
annotations=""
data="[object Object]"
- formattooltiptext="function () { [native code] }"
+ formattooltiptext="[Function]"
height="200"
includelegendavgmax="true"
legendaveragetext="Avg"
diff --git a/spec/lib/peek/views/memory_spec.rb b/spec/lib/peek/views/memory_spec.rb
new file mode 100644
index 00000000000..1f88aadfc54
--- /dev/null
+++ b/spec/lib/peek/views/memory_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Peek::Views::Memory, :request_store do
+ subject! { described_class.new }
+
+ before do
+ stub_memory_instrumentation
+ end
+
+ context 'with process_action.action_controller notification' do
+ it 'returns empty results when it has not yet fired' do
+ expect(subject.results).to eq({})
+ end
+
+ it 'returns memory instrumentation data when it has fired' do
+ publish_notification
+
+ expect(subject.results[:calls]).to eq('2 MB')
+ expect(subject.results[:details]).to all(have_key(:item_header))
+ expect(subject.results[:details]).to all(have_key(:item_content))
+ expect(subject.results[:summary]).to include('Objects allocated' => '200 k')
+ expect(subject.results[:summary]).to include('Allocator calls' => '500')
+ expect(subject.results[:summary]).to include('Large allocations' => '1 KB')
+ end
+ end
+
+ def stub_memory_instrumentation
+ start_memory = {
+ total_malloc_bytes: 1,
+ total_mallocs: 2,
+ total_allocated_objects: 3
+ }
+ allow(Gitlab::Memory::Instrumentation).to receive(:start_thread_memory_allocations).and_return(start_memory)
+ allow(Gitlab::Memory::Instrumentation).to receive(:measure_thread_memory_allocations).with(start_memory).and_return({
+ mem_total_bytes: 2_097_152,
+ mem_bytes: 1024,
+ mem_mallocs: 500,
+ mem_objects: 200_000
+ })
+ Gitlab::InstrumentationHelper.init_instrumentation_data
+ end
+
+ def publish_notification
+ headers = double
+ allow(headers).to receive(:env).and_return('action_dispatch.request_id': 'req-42')
+
+ ActiveSupport::Notifications.publish(
+ 'process_action.action_controller', Time.current - 1.second, Time.current, 'id', headers: headers
+ )
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index 851d6618866..a0961053bbb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1816,10 +1816,10 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
-"@vue/test-utils@1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.1.2.tgz#fdb487448dceefeaf3d01d465f7c836a3d666dbc"
- integrity sha512-utbIL7zn9c+SjhybPwh48lpWCiluFCbP1yyRNAy1fQsw/6hiNFioaWy05FoVAFIZXC5WwBf+5r4ypfM1j/nI4A==
+"@vue/test-utils@1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.2.0.tgz#3bc8c17ed549157275f0aec6b95da40887f7297f"
+ integrity sha512-poBTLqeJYNq1TXVhtVfnY8vELUVOFdJY8KZZoUuaAkIqPTWsxonU1M8nMWpZT+xEMrM+49+YcuEqtMHVD9Q9gw==
dependencies:
dom-event-types "^1.0.0"
lodash "^4.17.15"
@@ -3606,10 +3606,10 @@ core-js-pure@^3.0.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.1.3, core-js@^3.12.1:
- version "3.12.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.12.1.tgz#6b5af4ff55616c08a44d386f1f510917ff204112"
- integrity sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==
+core-js@^3.1.3, core-js@^3.13.0:
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.13.0.tgz#58ca436bf01d6903aee3d364089868d0d89fe58d"
+ integrity sha512-iWDbiyha1M5vFwPFmQnvRv+tJzGbFAm6XimJUT0NgHYW3xZEs1SkCAcasWSVFxpI2Xb/V1DDJckq3v90+bQnog==
core-js@~2.3.0:
version "2.3.0"