Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-06-22 00:07:53 +00:00
parent ee04416cd4
commit 3eb814543a
31 changed files with 233 additions and 64 deletions

View file

@ -13,7 +13,7 @@ module Ci
include Gitlab::Utils::StrongMemoize
include TaggableQueries
add_authentication_token_field :token, encrypted: -> { Feature.enabled?(:ci_runners_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
add_authentication_token_field :token, encrypted: :optional
enum access_level: {
not_protected: 0,

View file

@ -1,8 +0,0 @@
---
name: ci_runners_tokens_optional_encryption
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8638
rollout_issue_url:
milestone: '11.6'
type: development
group: group::pipeline execution
default_enabled: true

View file

@ -0,0 +1,8 @@
---
name: multiple_database_metrics
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63490
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333227
milestone: '14.1'
type: development
group: group::sharding
default_enabled: false

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
# External pipeline validation
# External pipeline validation **(FREE SELF)**
You can use an external service to validate a pipeline before it's created.

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, concepts, howto
---
# Caching in GitLab CI/CD
# Caching in GitLab CI/CD **(FREE)**
A cache is one or more files that a job downloads and saves. Subsequent jobs that use
the same cache don't have to download the files again, so they execute more quickly.

View file

@ -6,9 +6,9 @@ comments: false
type: index
---
# Docker integration
# Docker integration **(FREE)**
There are two primary ways to incorporate [Docker](https://www.docker.com) in your CI/CD workflow.
There are two primary ways to incorporate [Docker](https://www.docker.com) into your CI/CD workflow:
- **[Run your CI/CD jobs](using_docker_images.md) in Docker containers.**

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
# Use Docker to build Docker images
# Use Docker to build Docker images **(FREE)**
You can use GitLab CI/CD with Docker to create Docker images.
For example, you can create a Docker image of your application,

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
# Run your CI/CD jobs in Docker containers
# Run your CI/CD jobs in Docker containers **(FREE)**
You can run your CI/CD jobs in separate, isolated Docker containers.

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
# Use kaniko to build Docker images
# Use kaniko to build Docker images **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45512) in GitLab 11.2. Requires GitLab Runner 11.2 and above.

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
# How to enable or disable GitLab CI/CD
# How to enable or disable GitLab CI/CD **(FREE)**
To effectively use GitLab CI/CD, you need:

View file

@ -11,7 +11,7 @@ date: 2017-08-31
<!-- vale off -->
# Test and deploy Laravel applications with GitLab CI/CD and Envoy
# Test and deploy Laravel applications with GitLab CI/CD and Envoy **(FREE)**
## Introduction

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: tutorial
---
# Testing PHP projects
# Testing PHP projects **(FREE)**
This guide covers basic building instructions for PHP projects.

View file

@ -4,7 +4,7 @@ group: Package
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
---
# Publish npm packages to the GitLab Package Registry using semantic-release
# Publish npm packages to the GitLab Package Registry using semantic-release **(FREE)**
This guide demonstrates how to automatically publish npm packages to the [GitLab Package Registry](../../user/packages/npm_registry/index.md) by using [semantic-release](https://github.com/semantic-release/semantic-release).

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
# Using Git submodules with GitLab CI/CD
# Using Git submodules with GitLab CI/CD **(FREE)**
Use [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) to keep
a Git repository as a subdirectory of another Git repository. You can clone another

View file

@ -4,7 +4,7 @@ group: Pipeline Execution
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
---
# Jobs
# Jobs **(FREE)**
Pipeline configuration begins with jobs. Jobs are the most fundamental element of a `.gitlab-ci.yml` file.

View file

@ -6,7 +6,7 @@ type: reference, index
last_update: 2019-07-03
---
# Pipelines for merge requests
# Pipelines for merge requests **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/15310) in GitLab 11.6.

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
# Parent-child pipelines
# Parent-child pipelines **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) in GitLab 12.7.

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: tutorial
---
# Using SSH keys with GitLab CI/CD
# Using SSH keys with GitLab CI/CD **(FREE)**
GitLab currently doesn't have built-in support for managing SSH keys in a build
environment (where the GitLab Runner runs).

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
# Troubleshooting CI/CD
# Troubleshooting CI/CD **(FREE)**
GitLab provides several tools to help make troubleshooting your pipelines easier.

View file

@ -6,7 +6,7 @@ type: reference
---
<!-- markdownlint-disable MD044 -->
<!-- vale gitlab.Spelling = NO -->
# The .gitlab-ci.yml file
# The .gitlab-ci.yml file **(FREE)**
<!-- vale gitlab.Spelling = YES -->
<!-- markdownlint-enable MD044 -->

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
# GitLab CI/CD include examples
# GitLab CI/CD include examples **(FREE)**
In addition to the [`includes` examples](README.md#include) listed in the
[GitLab CI YAML reference](README.md), this page lists more variations of `include`

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
# GitLab CI/CD script syntax
# GitLab CI/CD script syntax **(FREE)**
You can use special syntax in [`script`](README.md#script) sections to:

View file

@ -22,7 +22,7 @@ which is exposed as an API endpoint at `/api/graphql`.
## Deep Dive
In March 2019, Nick Thomas hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
on the GitLab [GraphQL API](../api/graphql/index.md) to share his domain specific knowledge
on the GitLab [GraphQL API](../api/graphql/index.md) to share domain-specific knowledge
with anyone who may work in this part of the codebase in the future. You can find the
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
[recording on YouTube](https://www.youtube.com/watch?v=-9L_1MWrjkg), and the slides on
@ -83,7 +83,7 @@ developers must familiarize themselves with our [Deprecation and Removal process
Breaking changes are:
- Removing or renaming a field, argument, enum value or mutation.
- Removing or renaming a field, argument, enum value, or mutation.
- Changing the type of a field, argument or enum value.
- Raising the [complexity](#max-complexity) of a field or complexity multipliers in a resolver.
- Changing a field from being _not_ nullable (`null: false`) to nullable (`null: true`), as
@ -96,7 +96,7 @@ discussed in [Nullable fields](#nullable-fields).
Fields that use the [`feature_flag` property](#feature_flag-property) and the flag is disabled by default are exempt
from the deprecation process, and can be removed at any time without notice.
See the [deprecating fields and enum values](#deprecating-fields-arguments-and-enum-values) section for how to deprecate items.
See the [deprecating fields, arguments, and enum values](#deprecating-fields-arguments-and-enum-values) section for how to deprecate items.
## Global IDs
@ -110,6 +110,7 @@ See also:
- [Exposing Global IDs](#exposing-global-ids).
- [Mutation arguments](#object-identifier-arguments).
- [Deprecating Global IDs](#deprecate-global-ids).
We have a custom scalar type (`Types::GlobalIDType`) which should be used as the
type of input and output arguments when the value is a `GlobalID`. The benefits
@ -117,12 +118,12 @@ of using this type instead of `ID` are:
- it validates that the value is a `GlobalID`
- it parses it into a `GlobalID` before passing it to user code
- it can be parameterized on the type of the object (e.g.
- it can be parameterized on the type of the object (for example,
`GlobalIDType[Project]`) which offers even better validation and security.
Consider using this type for all new arguments and result types. Remember that
it is perfectly possible to parameterize this type with a concern or a
supertype, if you want to accept a wider range of objects (e.g.
supertype, if you want to accept a wider range of objects (such as
`GlobalIDType[Issuable]` vs `GlobalIDType[Issue]`).
## Types
@ -341,7 +342,7 @@ For example, instead of `latest_pipeline`, use `pipelines(last: 1)`.
By default, the API returns at most a maximum number of records defined in
[`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb)
per page within a connection and this will also be the default number of records
per page in a connection and this is also the default number of records
returned per page if no limiting arguments (`first:` or `last:`) are provided by a client.
The `max_page_size` argument can be used to specify a different page size limit
@ -369,7 +370,7 @@ Complexity is described in [our client documentation](../api/graphql/index.md#ma
Complexity limits are defined in [`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb).
By default, fields will add `1` to a query's complexity score. This can be overridden by
By default, fields add `1` to a query's complexity score. This can be overridden by
[providing a custom `complexity`](https://graphql-ruby.org/queries/complexity_and_depth.html) value for a field.
Developers should specify higher complexity for fields that cause more _work_ to be performed
@ -390,7 +391,7 @@ field :blob, type: Types::Snippets::BlobType,
calls_gitaly: true
```
This will increment the [`complexity` score](#field-complexity) of the field by `1`.
This increments the [`complexity` score](#field-complexity) of the field by `1`.
If a resolver calls Gitaly, it can be annotated with
`BaseResolver.calls_gitaly!`. This passes `calls_gitaly: true` to any
@ -480,7 +481,7 @@ You can refer to these guidelines to decide which approach to use:
The `feature_flag` property allows you to toggle the field's
[visibility](https://graphql-ruby.org/authorization/visibility.html)
within the GraphQL schema. This removes the field from the schema
in the GraphQL schema. This removes the field from the schema
when the flag is disabled.
A description is [appended](https://gitlab.com/gitlab-org/gitlab/-/blob/497b556/app/graphql/types/base_field.rb#L44-53)
@ -595,6 +596,105 @@ end
If the field, argument, or enum value being deprecated is not being replaced,
a descriptive deprecation `reason` should be given.
### Deprecate Global IDs
We use the [`rails/globalid`](https://github.com/rails/globalid) gem to generate and parse
Global IDs, so as such they are coupled to model names. When we rename a
model, its Global ID changes.
If the Global ID is used as an _argument_ type anywhere in the schema, then the Global ID
change would normally constitute a breaking change.
To continue to support clients using the old Global ID argument, we add a deprecation
to `Gitlab::GlobalId::Deprecations`.
NOTE:
If the Global ID is _only_ [exposed as a field](#exposing-global-ids) then we do not need to
deprecate it. We consider the change to the way a Global ID is expressed in a field to be
backwards-compatible. We expect that clients don't parse these values: they are meant to
be treated as opaque tokens, and any structure in them is incidental and not to be relied on.
**Example scenario:**
This example scenario is based on this [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62645).
A model named `PrometheusService` is to be renamed `Integrations::Prometheus`. The old model
name is used to create a Global ID type that is used as an argument for a mutation:
```ruby
# Mutations::UpdatePrometheus:
argument :id, Types::GlobalIDType[::PrometheusService],
required: true,
description: "The ID of the integration to mutate."
```
Clients call the mutation by passing a Global ID string that looks like
`"gid://gitlab/PrometheusService/1"`, named as `PrometheusServiceID`, as the `input.id` argument:
```graphql
mutation updatePrometheus($id: PrometheusServiceID!, $active: Boolean!) {
prometheusIntegrationUpdate(input: { id: $id, active: $active }) {
errors
integration {
active
}
}
}
```
We rename the model to `Integrations::Prometheus`, and then update the codebase with the new name.
When we come to update the mutation, we pass the renamed model to `Types::GlobalIDType[]`:
```ruby
# Mutations::UpdatePrometheus:
argument :id, Types::GlobalIDType[::Integrations::Prometheus],
required: true,
description: "The ID of the integration to mutate."
```
This would cause a breaking change to the mutation, as the API now rejects clients who
pass an `id` argument as `"gid://gitlab/PrometheusService/1"`, or that specify the argument
type as `PrometheusServiceID` in the query signature.
To allow clients to continue to interact with the mutation unchanged, edit the `DEPRECATIONS` constant in
`Gitlab::GlobalId::Deprecations` and add a new `Deprecation` to the array:
```ruby
DEPRECATIONS = [
Deprecation.new(old_model_name: 'PrometheusService', new_model_name: 'Integrations::Prometheus', milestone: '14.0')
].freeze
```
Then follow our regular [deprecation process](../api/graphql/index.md#deprecation-and-removal-process). To later remove
support for the former argument style, remove the `Deprecation`:
```ruby
DEPRECATIONS = [].freeze
```
During the deprecation period the API accepts these values for the argument:
Formatted as either:
- `"gid://gitlab/PrometheusService/1"`
- `"gid://gitlab/Integrations::Prometheus/1"`
And query signatures recognizes the type under the old and new type names, accepting either:
- `PrometheusServiceID`
- `IntegrationsPrometheusID`
NOTE:
Although queries that use the old name (`PrometheusServiceID` in this example) would be
considered valid and executable by the API, validator tools would consider them invalid.
This is because we are deprecating using a bespoke method outside of the
[`@deprecated` directive](https://spec.graphql.org/June2018/#sec--deprecated), so validators are not
aware of the support.
The documentation mentions that the old Global ID style is now deprecated.
See also [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations).
## Enums
@ -784,7 +884,7 @@ field :genus,
see: { 'Wikipedia page on genera' => 'https://wikipedia.org/wiki/Genus' }
```
This will render in our documentation as:
This renders in our documentation as:
```markdown
A taxonomic genus. See: [Wikipedia page on genera](https://wikipedia.org/wiki/Genus)
@ -859,11 +959,11 @@ overhead. If you are writing:
### Error handling
Resolvers may raise errors, which will be converted to top-level errors as
Resolvers may raise errors, which are converted to top-level errors as
appropriate. All anticipated errors should be caught and transformed to an
appropriate GraphQL error (see
[`Gitlab::Graphql::Errors`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/graphql/errors.rb)).
Any uncaught errors will be suppressed and the client will receive the message
Any uncaught errors are suppressed and the client receives the message
`Internal service error`.
The one special case is permission errors. In the REST API we return
@ -874,7 +974,7 @@ Query resolvers **should not raise errors for unauthorized resources**.
The rationale for this is that clients must not be able to distinguish between
the absence of a record and the presence of one they do not have access to. To
do so is a security vulnerability, since it leaks information we want to keep
do so is a security vulnerability, because it leaks information we want to keep
hidden.
In most cases you don't need to worry about this - this is handled correctly by
@ -1037,7 +1137,7 @@ class MyThingResolver < BaseResolver
end
```
By default, fields defined in `#preloads` will be preloaded if that field
By default, fields defined in `#preloads` are preloaded if that field
is selected in the query. Occasionally, finer control may be
needed to avoid preloading too much or incorrect content.
@ -1121,7 +1221,7 @@ available in the `Resolver` class as `parent`.
To find the parent object in your `Presenter` class:
1. Add the parent object to the GraphQL `context` from within your resolver's `resolve` method:
1. Add the parent object to the GraphQL `context` from your resolver's `resolve` method:
```ruby
def resolve(**args)
@ -1316,6 +1416,8 @@ Where an object has an `iid`, prefer to use the `full_path` or `group_path`
of its parent in combination with its `iid` as arguments to identify an
object rather than its `id`.
See also [Deprecate Global IDs](#deprecate-global-ids).
### Fields
In the most common situations, a mutation would return 2 fields:
@ -1327,7 +1429,7 @@ In the most common situations, a mutation would return 2 fields:
By inheriting any new mutations from `Mutations::BaseMutation` the
`errors` field is automatically added. A `clientMutationId` field is
also added, this can be used by the client to identify the result of a
single mutation when multiple are performed within a single request.
single mutation when multiple are performed in a single request.
### The `resolve` method
@ -1447,7 +1549,7 @@ There are three states a mutation response can be in:
#### Success
In the happy path, errors *may* be returned, along with the anticipated payload, but
if everything was successful, then `errors` should be an empty array, since
if everything was successful, then `errors` should be an empty array, because
there are no problems we need to inform the user of.
```javascript
@ -1524,7 +1626,7 @@ of errors should be treated as internal, and not shown to the user in specific
detail.
We need to inform the user when the mutation fails, but we do not need to
tell them why, since they cannot have caused it, and nothing they can do
tell them why, because they cannot have caused it, and nothing they can do
fixes it, although we may offer to retry the mutation.
#### Categorizing errors
@ -1544,7 +1646,7 @@ See also the [frontend GraphQL guide](../development/fe_guide/graphql.md#handlin
### Aliasing and deprecating mutations
The `#mount_aliased_mutation` helper allows us to alias a mutation as
another name within `MutationType`.
another name in `MutationType`.
For example, to alias a mutation called `FooMutation` as `BarMutation`:
@ -1565,7 +1667,7 @@ mount_aliased_mutation 'UpdateFoo',
```
Deprecated mutations should be added to `Types::DeprecatedMutations` and
tested for within the unit test of `Types::MutationType`. The merge request
tested for in the unit test of `Types::MutationType`. The merge request
[!34798](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34798)
can be referred to as an example of this, including the method of testing
deprecated aliased mutations.
@ -1591,7 +1693,7 @@ We cannot test subscriptions using GraphiQL, because they require an Action Cabl
All fields under `Types::SubscriptionType` are subscriptions that clients can subscribe to. These fields require a subscription class,
which is a descendant of `Subscriptions::BaseSubscription` and is stored under `app/graphql/subscriptions`.
The arguments required to subscribe and the fields that are returned are defined within the subscription class. Multiple fields can share
The arguments required to subscribe and the fields that are returned are defined in the subscription class. Multiple fields can share
the same subscription class if they have the same arguments and return the same fields.
This class runs during the initial subscription request and subsequent updates. You can read more about this in the
@ -1623,8 +1725,8 @@ as normal.
Sometimes a mutation or resolver may accept a number of optional
arguments, but we still want to validate that at least one of the optional
arguments is provided. In this situation, consider using the `#ready?`
method within your mutation or resolver to provide the validation. The
`#ready?` method is called before any work is done within the
method in your mutation or resolver to provide the validation. The
`#ready?` method is called before any work is done in the
`#resolve` method.
Example:
@ -1698,7 +1800,7 @@ For speed, you should test most logic in unit tests instead of integration tests
However, integration tests that check if data is returned verify the following
additional items:
- The mutation is actually queryable within the schema (was mounted in `MutationType`).
- The mutation is actually queryable in the schema (was mounted in `MutationType`).
- The data returned by a resolver or mutation correctly matches the
[return types](https://graphql-ruby.org/fields/introduction.html#field-return-type) of
the fields and resolves without errors.
@ -1846,7 +1948,7 @@ to protect server resources from overly ambitious or malicious queries.
These values can be set as defaults and overridden in specific queries as needed.
The complexity values can be set per object as well, and the final query complexity is
evaluated based on how many objects are being returned. This is useful
for objects that are expensive (e.g. requiring Gitaly calls).
for objects that are expensive (such as requiring Gitaly calls).
For example, a conditional complexity method in a resolver:

View file

@ -4,7 +4,7 @@ group: Pipeline Execution
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
---
# CI/CD YAML reference style guide
# CI/CD YAML reference style guide **(FREE)**
The CI/CD YAML reference uses a standard style to make it easier to use and update.

View file

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, concepts, howto
---
# CI/CD development documentation
# CI/CD development documentation **(FREE)**
Development guides that are specific to CI/CD are listed here.

View file

@ -333,6 +333,16 @@ module Gitlab
end
end
def self.dbname(ar_connection)
if ar_connection.respond_to?(:pool) &&
ar_connection.pool.respond_to?(:db_config) &&
ar_connection.pool.db_config.respond_to?(:database)
return ar_connection.pool.db_config.database
end
'unknown'
end
# inside_transaction? will return true if the caller is running within a transaction. Handles special cases
# when running inside a test environment, where tests may be wrapped in transactions
def self.inside_transaction?

View file

@ -72,6 +72,14 @@ module Gitlab
DB_LOAD_BALANCING_DURATIONS.each do |duration|
payload[duration] = ::Gitlab::SafeRequestStore[duration].to_f.round(3)
end
if Feature.enabled?(:multiple_database_metrics, default_enabled: :yaml)
::Gitlab::SafeRequestStore[:duration_by_database]&.each do |dbname, duration_by_role|
duration_by_role.each do |db_role, duration|
payload[:"db_#{db_role}_#{dbname}_duration_s"] = duration.to_f.round(3)
end
end
end
end
end
end
@ -93,9 +101,18 @@ module Gitlab
buckets ::Gitlab::Metrics::Subscribers::ActiveRecord::SQL_DURATION_BUCKET
end
return unless ::Gitlab::SafeRequestStore.active?
duration = event.duration / 1000.0
duration_key = "db_#{db_role}_duration_s".to_sym
::Gitlab::SafeRequestStore[duration_key] = (::Gitlab::SafeRequestStore[duration_key].presence || 0) + duration
# Per database metrics
dbname = ::Gitlab::Database.dbname(event.payload[:connection])
::Gitlab::SafeRequestStore[:duration_by_database] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][dbname] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][dbname][db_role] ||= 0
::Gitlab::SafeRequestStore[:duration_by_database][dbname][db_role] += duration
end
def ignored_query?(payload)

View file

@ -414,6 +414,23 @@ RSpec.describe Gitlab::Database do
end
end
describe '.dbname' do
it 'returns the dbname for the connection' do
connection = ActiveRecord::Base.connection
expect(described_class.dbname(connection)).to be_a(String)
expect(described_class.dbname(connection)).to eq(connection.pool.db_config.database)
end
context 'when the pool is a NullPool' do
it 'returns unknown' do
connection = double(:active_record_connection, pool: ActiveRecord::ConnectionAdapters::NullPool.new)
expect(described_class.dbname(connection)).to eq('unknown')
end
end
end
describe '#true_value' do
it 'returns correct value' do
expect(described_class.true_value).to eq "'t'"

View file

@ -7,7 +7,7 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do
let(:env) { {} }
let(:subscriber) { described_class.new }
let(:connection) { double(:connection) }
let(:connection) { ActiveRecord::Base.connection }
describe '#transaction' do
let(:web_transaction) { double('Gitlab::Metrics::WebTransaction') }

View file

@ -298,6 +298,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
end
let(:dbname) { ::Gitlab::Database.dbname(ActiveRecord::Base.connection) }
let(:expected_end_payload_with_db) do
expected_end_payload.merge(
'db_duration_s' => a_value >= 0.1,
@ -311,7 +313,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
'db_primary_count' => a_value >= 1,
'db_primary_cached_count' => 0,
'db_primary_wal_count' => 0,
'db_primary_duration_s' => a_value > 0
'db_primary_duration_s' => a_value > 0,
"db_primary_#{dbname}_duration_s" => a_value > 0
)
end

View file

@ -5,9 +5,10 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
2.times do
Gitlab::WithRequestStore.with_request_store do
subscriber.sql(event)
connection = event.payload[:connection]
if db_role == :primary
expect(described_class.db_counter_payload).to eq(
expected = {
db_count: record_query ? 1 : 0,
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0,
@ -19,9 +20,10 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_replica_duration_s: 0.0,
db_primary_wal_count: record_wal_query ? 1 : 0,
db_replica_wal_count: 0
)
}
expected[:"db_primary_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query
elsif db_role == :replica
expect(described_class.db_counter_payload).to eq(
expected = {
db_count: record_query ? 1 : 0,
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0,
@ -33,14 +35,32 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_replica_duration_s: record_query ? 0.002 : 0,
db_replica_wal_count: record_wal_query ? 1 : 0,
db_primary_wal_count: 0
)
}
expected[:"db_replica_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query
else
expect(described_class.db_counter_payload).to eq(
expected = {
db_count: record_query ? 1 : 0,
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0
)
}
end
expect(described_class.db_counter_payload).to eq(expected)
end
end
end
context 'when multiple_database_metrics is disabled' do
before do
stub_feature_flags(multiple_database_metrics: false)
end
it 'does not include per database metrics' do
Gitlab::WithRequestStore.with_request_store do
subscriber.sql(event)
connection = event.payload[:connection]
expect(described_class.db_counter_payload).not_to include(:"db_replica_#{::Gitlab::Database.dbname(connection)}_duration_s")
end
end
end