Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
8bc752f208
commit
47d07def16
29 changed files with 272 additions and 320 deletions
|
@ -130,7 +130,6 @@
|
|||
"Ubuntu",
|
||||
"Ultra Auth",
|
||||
"Unicorn",
|
||||
"unicorn-worker-killer",
|
||||
"URL",
|
||||
"WebdriverIO",
|
||||
"YAML",
|
||||
|
|
1
Gemfile
1
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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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` }"
|
||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
|||
},
|
||||
props: {
|
||||
estimate: {
|
||||
type: Number,
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -73,6 +73,11 @@ export default {
|
|||
header: s__('PerformanceBar|External Http calls'),
|
||||
keys: ['label', 'code', 'proxy', 'error'],
|
||||
},
|
||||
{
|
||||
metric: 'memory',
|
||||
header: s__('PerformanceBar|Memory'),
|
||||
keys: ['item_header', 'item_content'],
|
||||
},
|
||||
{
|
||||
metric: 'total',
|
||||
header: s__('PerformanceBar|Frontend resources'),
|
||||
|
|
|
@ -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
|
||||
|
|
17
config.ru
17
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|
|
||||
|
|
|
@ -130,13 +130,6 @@
|
|||
:why: http://unicorn.bogomips.org/LICENSE.html
|
||||
: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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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`). |
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
76
lib/peek/views/memory.rb
Normal file
76
lib/peek/views/memory.rb
Normal file
|
@ -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
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 || {});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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 } });
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(wrapper.emitted()).toEqual({
|
||||
focus: [[]],
|
||||
});
|
||||
await findTextarea().trigger('focus');
|
||||
|
||||
expect(wrapper.emitted()).toEqual({
|
||||
focus: [[]],
|
||||
});
|
||||
});
|
||||
|
||||
it('should render reply button', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findTextarea().attributes('placeholder')).toEqual(placeholderText);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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"
|
||||
|
|
53
spec/lib/peek/views/memory_spec.rb
Normal file
53
spec/lib/peek/views/memory_spec.rb
Normal file
|
@ -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
|
16
yarn.lock
16
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"
|
||||
|
|
Loading…
Reference in a new issue