Commit 09ffaae1 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent b3e4ec8e
...@@ -37,7 +37,6 @@ import GlFieldErrors from './gl_field_errors'; ...@@ -37,7 +37,6 @@ import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers'; import initUserPopovers from './user_popovers';
import { initUserTracking } from './tracking'; import { initUserTracking } from './tracking';
import { __ } from './locale'; import { __ } from './locale';
import initPrivacyPolicyUpdateCallout from './privacy_policy_update_callout';
import 'ee_else_ce/main_ee'; import 'ee_else_ce/main_ee';
...@@ -97,7 +96,6 @@ function deferredInitialisation() { ...@@ -97,7 +96,6 @@ function deferredInitialisation() {
initUsagePingConsent(); initUsagePingConsent();
initUserPopovers(); initUserPopovers();
initUserTracking(); initUserTracking();
initPrivacyPolicyUpdateCallout();
if (document.querySelector('.search')) initSearchAutocomplete(); if (document.querySelector('.search')) initSearchAutocomplete();
......
import PersistentUserCallout from '~/persistent_user_callout';
function initPrivacyPolicyUpdateCallout() {
const callout = document.querySelector('.js-privacy-policy-update');
PersistentUserCallout.factory(callout);
}
export default initPrivacyPolicyUpdateCallout;
...@@ -17,6 +17,4 @@ ...@@ -17,6 +17,4 @@
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" } %div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
.content{ id: "content-body" } .content{ id: "content-body" }
= render "layouts/flash", extra_flash_class: 'limit-container-width' = render "layouts/flash", extra_flash_class: 'limit-container-width'
- if Gitlab.com?
= render_if_exists "layouts/privacy_policy_update_callout"
= yield = yield
---
title: Record latencies for Sidekiq failures
merge_request: 18909
author:
type: performance
---
title: Pipeline vulnerability dashboard sort vulnerabilities by severity then confidence
merge_request: 18863
author:
type: fixed
...@@ -120,3 +120,4 @@ ...@@ -120,3 +120,4 @@
- [update_external_pull_requests, 3] - [update_external_pull_requests, 3]
- [refresh_license_compliance_checks, 2] - [refresh_license_compliance_checks, 2]
- [design_management_new_version, 1] - [design_management_new_version, 1]
- [epics, 2]
# frozen_string_literal: true
class AddSourcingEpicDates < ActiveRecord::Migration[5.1]
DOWNTIME = false
def change
add_column :epics, :start_date_sourcing_epic_id, :integer
add_column :epics, :due_date_sourcing_epic_id, :integer
end
end
# frozen_string_literal: true
class AddSourcingEpicDatesFks < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :epics, :start_date_sourcing_epic_id, where: 'start_date_sourcing_epic_id is not null'
add_concurrent_index :epics, :due_date_sourcing_epic_id, where: 'due_date_sourcing_epic_id is not null'
add_concurrent_foreign_key :epics, :epics, column: :start_date_sourcing_epic_id, on_delete: :nullify
add_concurrent_foreign_key :epics, :epics, column: :due_date_sourcing_epic_id, on_delete: :nullify
end
def down
remove_foreign_key_if_exists :epics, column: :start_date_sourcing_epic_id
remove_foreign_key_if_exists :epics, column: :due_date_sourcing_epic_id
remove_concurrent_index :epics, :start_date_sourcing_epic_id
remove_concurrent_index :epics, :due_date_sourcing_epic_id
end
end
...@@ -1423,15 +1423,19 @@ ActiveRecord::Schema.define(version: 2019_10_17_045817) do ...@@ -1423,15 +1423,19 @@ ActiveRecord::Schema.define(version: 2019_10_17_045817) do
t.integer "parent_id" t.integer "parent_id"
t.integer "relative_position" t.integer "relative_position"
t.integer "state_id", limit: 2, default: 1, null: false t.integer "state_id", limit: 2, default: 1, null: false
t.integer "start_date_sourcing_epic_id"
t.integer "due_date_sourcing_epic_id"
t.index ["assignee_id"], name: "index_epics_on_assignee_id" t.index ["assignee_id"], name: "index_epics_on_assignee_id"
t.index ["author_id"], name: "index_epics_on_author_id" t.index ["author_id"], name: "index_epics_on_author_id"
t.index ["closed_by_id"], name: "index_epics_on_closed_by_id" t.index ["closed_by_id"], name: "index_epics_on_closed_by_id"
t.index ["due_date_sourcing_epic_id"], name: "index_epics_on_due_date_sourcing_epic_id", where: "(due_date_sourcing_epic_id IS NOT NULL)"
t.index ["end_date"], name: "index_epics_on_end_date" t.index ["end_date"], name: "index_epics_on_end_date"
t.index ["group_id"], name: "index_epics_on_group_id" t.index ["group_id"], name: "index_epics_on_group_id"
t.index ["iid"], name: "index_epics_on_iid" t.index ["iid"], name: "index_epics_on_iid"
t.index ["milestone_id"], name: "index_milestone" t.index ["milestone_id"], name: "index_milestone"
t.index ["parent_id"], name: "index_epics_on_parent_id" t.index ["parent_id"], name: "index_epics_on_parent_id"
t.index ["start_date"], name: "index_epics_on_start_date" t.index ["start_date"], name: "index_epics_on_start_date"
t.index ["start_date_sourcing_epic_id"], name: "index_epics_on_start_date_sourcing_epic_id", where: "(start_date_sourcing_epic_id IS NOT NULL)"
end end
create_table "events", id: :serial, force: :cascade do |t| create_table "events", id: :serial, force: :cascade do |t|
...@@ -4158,7 +4162,9 @@ ActiveRecord::Schema.define(version: 2019_10_17_045817) do ...@@ -4158,7 +4162,9 @@ ActiveRecord::Schema.define(version: 2019_10_17_045817) do
add_foreign_key "epic_issues", "epics", on_delete: :cascade add_foreign_key "epic_issues", "epics", on_delete: :cascade
add_foreign_key "epic_issues", "issues", on_delete: :cascade add_foreign_key "epic_issues", "issues", on_delete: :cascade
add_foreign_key "epic_metrics", "epics", on_delete: :cascade add_foreign_key "epic_metrics", "epics", on_delete: :cascade
add_foreign_key "epics", "epics", column: "due_date_sourcing_epic_id", name: "fk_013c9f36ca", on_delete: :nullify
add_foreign_key "epics", "epics", column: "parent_id", name: "fk_25b99c1be3", on_delete: :cascade add_foreign_key "epics", "epics", column: "parent_id", name: "fk_25b99c1be3", on_delete: :cascade
add_foreign_key "epics", "epics", column: "start_date_sourcing_epic_id", name: "fk_9d480c64b2", on_delete: :nullify
add_foreign_key "epics", "milestones", on_delete: :nullify add_foreign_key "epics", "milestones", on_delete: :nullify
add_foreign_key "epics", "namespaces", column: "group_id", name: "fk_f081aa4489", on_delete: :cascade add_foreign_key "epics", "namespaces", column: "group_id", name: "fk_f081aa4489", on_delete: :cascade
add_foreign_key "epics", "users", column: "assignee_id", name: "fk_dccd3f98fc", on_delete: :nullify add_foreign_key "epics", "users", column: "assignee_id", name: "fk_dccd3f98fc", on_delete: :nullify
......
...@@ -50,12 +50,14 @@ Example response: ...@@ -50,12 +50,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": []
...@@ -102,12 +104,14 @@ Example response: ...@@ -102,12 +104,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": []
...@@ -189,12 +193,14 @@ Example response: ...@@ -189,12 +193,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": []
...@@ -241,12 +247,14 @@ Example response: ...@@ -241,12 +247,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": []
......
...@@ -14,9 +14,13 @@ The [epic issues API](epic_issues.md) allows you to interact with issues associa ...@@ -14,9 +14,13 @@ The [epic issues API](epic_issues.md) allows you to interact with issues associa
> [Introduced][ee-6448] in GitLab 11.3. > [Introduced][ee-6448] in GitLab 11.3.
Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission, additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`, and four date fields `start_date_fixed`, `start_date_from_milestones`, `due_date_fixed` and `due_date_from_milestones`. Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission,
additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`,
and four date fields `start_date_fixed`, `start_date_from_inherited_source`, `due_date_fixed` and `due_date_from_inherited_source`.
`end_date` has been deprecated in favor of `due_date`. - `end_date` has been deprecated in favor of `due_date`.
- `start_date_from_milestones` has been deprecated in favor of `start_date_from_inherited_source`
- `due_date_from_milestones` has been deprecated in favor of `due_date_from_inherited_source`
## Epics pagination ## Epics pagination
...@@ -80,12 +84,14 @@ Example response: ...@@ -80,12 +84,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z",
...@@ -136,12 +142,14 @@ Example response: ...@@ -136,12 +142,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z",
...@@ -204,12 +212,14 @@ Example response: ...@@ -204,12 +212,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z",
...@@ -272,12 +282,14 @@ Example response: ...@@ -272,12 +282,14 @@ Example response:
"start_date": null, "start_date": null,
"start_date_is_fixed": false, "start_date_is_fixed": false,
"start_date_fixed": null, "start_date_fixed": null,
"start_date_from_milestones": null, "start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"end_date": "2018-07-31", "start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31", "due_date": "2018-07-31",
"due_date_is_fixed": false, "due_date_is_fixed": false,
"due_date_fixed": null, "due_date_fixed": null,
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z", "closed_at": "2018-08-18T12:22:05.239Z",
......
...@@ -43,14 +43,14 @@ a new presenter specifically for GraphQL. ...@@ -43,14 +43,14 @@ a new presenter specifically for GraphQL.
The presenter is initialized using the object resolved by a field, and The presenter is initialized using the object resolved by a field, and
the context. the context.
### Exposing Global ids ### Exposing Global IDs
When exposing an `id` field on a type, we will by default try to When exposing an `ID` field on a type, we will by default try to
expose a global id by calling `to_global_id` on the resource being expose a global ID by calling `to_global_id` on the resource being
rendered. rendered.
To override this behaviour, you can implement an `id` method on the To override this behaviour, you can implement an `id` method on the
type for which you are exposing an id. Please make sure that when type for which you are exposing an ID. Please make sure that when
exposing a `GraphQL::ID_TYPE` using a custom method that it is exposing a `GraphQL::ID_TYPE` using a custom method that it is
globally unique. globally unique.
...@@ -350,7 +350,10 @@ To find objects to display in a field, we can add resolvers to ...@@ -350,7 +350,10 @@ To find objects to display in a field, we can add resolvers to
`app/graphql/resolvers`. `app/graphql/resolvers`.
Arguments can be defined within the resolver, those arguments will be Arguments can be defined within the resolver, those arguments will be
made available to the fields using the resolver. made available to the fields using the resolver. When exposing a model
that had an internal ID (`iid`), prefer using that in combination with
the namespace path as arguments in a resolver over a database
ID. Othewise use a [globally unique ID](#exposing-global-ids).
We already have a `FullPathLoader` that can be included in other We already have a `FullPathLoader` that can be included in other
resolvers to quickly find Projects and Namespaces which will have a resolvers to quickly find Projects and Namespaces which will have a
...@@ -365,6 +368,10 @@ actions. In the same way a GET-request should not modify data, we ...@@ -365,6 +368,10 @@ actions. In the same way a GET-request should not modify data, we
cannot modify data in a regular GraphQL-query. We can however in a cannot modify data in a regular GraphQL-query. We can however in a
mutation. mutation.
To find objects for a mutation, arguments need to be specified. As with
[resolvers](#resolvers), prefer using internal ID or, if needed, a
global ID rather than the database ID.
### Fields ### Fields
In the most common situations, a mutation would return 2 fields: In the most common situations, a mutation would return 2 fields:
......
...@@ -92,24 +92,44 @@ To remove a child epic from a parent epic: ...@@ -92,24 +92,44 @@ To remove a child epic from a parent epic:
## Start date and due date ## Start date and due date
To set a **Start date** and **Due date** for an epic, you can choose either of the following: To set a **Start date** and **Due date** for an epic, select one of the following:
- **Fixed**: Enter a fixed value. - **Fixed**: Enter a fixed value.
- **From milestones:** Inherit a dynamic value from the issues added to the epic. - **From milestones**: Inherit a dynamic value from the issues added to the epic.
- **Inherited**: Inherit a dynamic value from the issues added to the epic. ([Introduced](https://gitlab.com/gitlab-org/gitlab/issues/7332) in GitLab 12.5 to replace **From milestones**).
If you select **From milestones** for the start date, GitLab will automatically set the ### Milestones
date to be earliest start date across all milestones that are currently assigned
to the issues that are added to the epic. Similarly, if you select "From milestones"
for the due date, GitLab will set it to be the latest due date across all
milestones that are currently assigned to those issues.
These are dynamic dates which are recalculated immediately if any of the following occur: If you select **From milestones** for the start date, GitLab will automatically set the date to be earliest
start date across all milestones that are currently assigned to the issues that are added to the epic.
Similarly, if you select **From milestones** for the due date, GitLab will set it to be the latest due date across
all milestones that are currently assigned to those issues.
These are dynamic dates which are recalculated if any of the following occur:
- Milestones are re-assigned to the issues. - Milestones are re-assigned to the issues.
- Milestone dates change. - Milestone dates change.
- Issues are added or removed from the epic. - Issues are added or removed from the epic.
## Roadmap ### Inherited
If you select **Inherited** for the start date, GitLab will scan all child epics and issues assigned to the epic,
and will set the start date to match the earliest found start date or milestone. Similarly, if you select
**Inherited** for the due date, GitLab will set the due date to match the latest due date or milestone
found among its child epics and issues.
These are dynamic dates and recalculated if any of the following occur:
- A child epic's dates change.
- Milestones are reassigned to an issue.
- A milestone's dates change.
- Issues are added to, or removed from, the epic.
Because the epic's dates can inherit dates from its children, the start date and due date propagate from the bottom to the top.
If the start date of a child epic on the lowest level changes, that becomes the earliest possible start date for its parent epic,
then the parent epic's start date will reflect the change and this will propagate upwards to the top epic.
## Roadmap in epics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.10. > [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.10.
......
...@@ -26,7 +26,7 @@ Epics in the view can be sorted by: ...@@ -26,7 +26,7 @@ Epics in the view can be sorted by:
Each option contains a button that toggles the sort order between **ascending** and **descending**. The sort option and order will be persisted when browsing Epics, Each option contains a button that toggles the sort order between **ascending** and **descending**. The sort option and order will be persisted when browsing Epics,
including the [epics list view](../epics/index.md). including the [epics list view](../epics/index.md).
Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap). Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics).
## Timeline duration ## Timeline duration
......
...@@ -21,29 +21,35 @@ module Gitlab ...@@ -21,29 +21,35 @@ module Gitlab
@metrics[:sidekiq_jobs_retried_total].increment(labels, 1) @metrics[:sidekiq_jobs_retried_total].increment(labels, 1)
end end
job_succeeded = false
monotonic_time_start = Gitlab::Metrics::System.monotonic_time
job_thread_cputime_start = get_thread_cputime job_thread_cputime_start = get_thread_cputime
begin
realtime = Benchmark.realtime do
yield yield
end job_succeeded = true
ensure
monotonic_time_end = Gitlab::Metrics::System.monotonic_time
job_thread_cputime_end = get_thread_cputime
job_thread_cputime_end = get_thread_cputime monotonic_time = monotonic_time_end - monotonic_time_start
job_thread_cputime = job_thread_cputime_end - job_thread_cputime_start job_thread_cputime = job_thread_cputime_end - job_thread_cputime_start
@metrics[:sidekiq_jobs_cpu_seconds].observe(labels, job_thread_cputime)
@metrics[:sidekiq_jobs_completion_seconds].observe(labels, realtime) # sidekiq_running_jobs, sidekiq_jobs_failed_total should not include the job_status label
rescue Exception # rubocop: disable Lint/RescueException @metrics[:sidekiq_running_jobs].increment(labels, -1)
@metrics[:sidekiq_jobs_failed_total].increment(labels, 1) @metrics[:sidekiq_jobs_failed_total].increment(labels, 1) unless job_succeeded
raise
ensure # job_status: done, fail match the job_status attribute in structured logging
@metrics[:sidekiq_running_jobs].increment(labels, -1) labels[:job_status] = job_succeeded ? :done : :fail
@metrics[:sidekiq_jobs_cpu_seconds].observe(labels, job_thread_cputime)
@metrics[:sidekiq_jobs_completion_seconds].observe(labels, monotonic_time)
end
end end
private private
def init_metrics def init_metrics
{ {
sidekiq_jobs_cpu_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_cpu_seconds, 'Seconds of cpu time to run sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS), sidekiq_jobs_cpu_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_cpu_seconds, 'Seconds of cpu time to run sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_completion_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_completion_seconds, 'Seconds to complete sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS), sidekiq_jobs_completion_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_completion_seconds, 'Seconds to complete sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_failed_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_failed_total, 'Sidekiq jobs failed'), sidekiq_jobs_failed_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_failed_total, 'Sidekiq jobs failed'),
sidekiq_jobs_retried_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_retried_total, 'Sidekiq jobs retried'), sidekiq_jobs_retried_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_retried_total, 'Sidekiq jobs retried'),
......
...@@ -29,7 +29,7 @@ module Gitlab ...@@ -29,7 +29,7 @@ module Gitlab
end end
if fragments.any? if fragments.any?
fragments.join("\n#{union_keyword}\n") "(" + fragments.join(")\n#{union_keyword}\n(") + ")"
else else
'NULL' 'NULL'
end end
......
...@@ -7427,9 +7427,6 @@ msgstr "" ...@@ -7427,9 +7427,6 @@ msgstr ""
msgid "From merge request merge until deploy to production" msgid "From merge request merge until deploy to production"
msgstr "" msgstr ""
msgid "From milestones:"
msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list" msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "" msgstr ""
...@@ -9019,6 +9016,9 @@ msgstr "" ...@@ -9019,6 +9016,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}." msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr "" msgstr ""
msgid "Inherited:"
msgstr ""
msgid "Inline" msgid "Inline"
msgstr "" msgstr ""
...@@ -11522,9 +11522,6 @@ msgstr "" ...@@ -11522,9 +11522,6 @@ msgstr ""
msgid "Other visibility settings have been disabled by the administrator." msgid "Other visibility settings have been disabled by the administrator."
msgstr "" msgstr ""
msgid "Our Privacy Policy has changed, please visit %{privacy_policy_link} to review these changes."
msgstr ""
msgid "Outbound requests" msgid "Outbound requests"
msgstr "" msgstr ""
......
...@@ -96,30 +96,14 @@ describe ApplicationController do ...@@ -96,30 +96,14 @@ describe ApplicationController do
request.path = '/-/peek' request.path = '/-/peek'
end end
# TODO: it_behaves_like 'not setting gon variables'
# remove line below once `privacy_policy_update_callout`
# feature flag is removed and `gon` reverts back to
# to not setting any variables.
if Gitlab.ee?
it_behaves_like 'setting gon variables'
else
it_behaves_like 'not setting gon variables'
end
end end
end end
context 'with json format' do context 'with json format' do
let(:format) { :json } let(:format) { :json }
# TODO: it_behaves_like 'not setting gon variables'
# remove line below once `privacy_policy_update_callout`
# feature flag is removed and `gon` reverts back to
# to not setting any variables.
if Gitlab.ee?
it_behaves_like 'setting gon variables'
else
it_behaves_like 'not setting gon variables'
end
end end
end end
......
...@@ -44,12 +44,14 @@ describe Gitlab::SidekiqMiddleware::Metrics do ...@@ -44,12 +44,14 @@ describe Gitlab::SidekiqMiddleware::Metrics do
it 'sets queue specific metrics' do it 'sets queue specific metrics' do
labels = { queue: :test } labels = { queue: :test }
labels_with_job_status = { queue: :test, job_status: :done }
allow(middleware).to receive(:get_thread_cputime).and_return(1, 3) allow(middleware).to receive(:get_thread_cputime).and_return(1, 3)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(2, 3)
expect(user_execution_seconds_metric).to receive(:observe).with(labels, 2)
expect(running_jobs_metric).to receive(:increment).with(labels, 1) expect(running_jobs_metric).to receive(:increment).with(labels, 1)
expect(running_jobs_metric).to receive(:increment).with(labels, -1) expect(running_jobs_metric).to receive(:increment).with(labels, -1)
expect(completion_seconds_metric).to receive(:observe).with(labels, kind_of(Numeric)) expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, 2)
expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, 1)
middleware.call(worker, {}, :test) { nil } middleware.call(worker, {}, :test) { nil }
end end
...@@ -74,8 +76,18 @@ describe Gitlab::SidekiqMiddleware::Metrics do ...@@ -74,8 +76,18 @@ describe Gitlab::SidekiqMiddleware::Metrics do
context 'when error is raised' do context 'when error is raised' do
it 'sets sidekiq_jobs_failed_total and reraises' do it 'sets sidekiq_jobs_failed_total and reraises' do
expect(failed_total_metric).to receive(:increment) labels = { queue: :test }
expect { middleware.call(worker, {}, :test) { raise } }.to raise_error labels_with_job_status = { queue: :test, job_status: :fail }
allow(middleware).to receive(:get_thread_cputime).and_return(1, 4)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(2, 6)
expect(running_jobs_metric).to receive(:increment).with(labels, 1)
expect(running_jobs_metric).to receive(:increment).with(labels, -1)
expect(failed_total_metric).to receive(:increment).with(labels, 1)
expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, 3)
expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, 4)
expect { middleware.call(worker, {}, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
end end
end end
end end
......
...@@ -20,7 +20,7 @@ describe Gitlab::SQL::RecursiveCTE do ...@@ -20,7 +20,7 @@ describe Gitlab::SQL::RecursiveCTE do
[rel1.except(:order).to_sql, rel2.except(:order).to_sql] [rel1.except(:order).to_sql, rel2.except(:order).to_sql]
end end
expect(sql).to eq("#{name} AS (#{sql1}\nUNION\n#{sql2})") expect(sql).to eq("#{name} AS ((#{sql1})\nUNION\n(#{sql2}))")
end end
end end
......
...@@ -14,7 +14,7 @@ describe Gitlab::SQL::Union do ...@@ -14,7 +14,7 @@ describe Gitlab::SQL::Union do
it 'returns a String joining relations together using a UNION' do it 'returns a String joining relations together using a UNION' do
union = described_class.new([relation_1, relation_2]) union = described_class.new([relation_1, relation_2])
expect(union.to_sql).to eq("#{to_sql(relation_1)}\nUNION\n#{to_sql(relation_2)}") expect(union.to_sql).to eq("(#{to_sql(relation_1)})\nUNION\n(#{to_sql(relation_2)})")
end end
it 'skips Model.none segements' do it 'skips Model.none segements' do
...@@ -22,7 +22,7 @@ describe Gitlab::SQL::Union do ...@@ -22,7 +22,7 @@ describe Gitlab::SQL::Union do
union = described_class.new([empty_relation, relation_1, relation_2]) union = described_class.new([empty_relation, relation_1, relation_2])
expect {User.where("users.id IN (#{union.to_sql})").to_a}.not_to raise_error expect {User.where("users.id IN (#{union.to_sql})").to_a}.not_to raise_error
expect(union.to_sql).to eq("#{to_sql(relation_1)}\nUNION\n#{to_sql(relation_2)}") expect(union.to_sql).to eq("(#{to_sql(relation_1)})\nUNION\n(#{to_sql(relation_2)})")
end end
it 'uses UNION ALL when removing duplicates is disabled' do it 'uses UNION ALL when removing duplicates is disabled' do
......
require 'spec_helper' require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20191017045817_schedule_fix_gitlab_com_pages_access_level.rb') require Rails.root.join('db', 'post_migrate', '20191017045817_schedule_fix_gitlab_com_pages_access_level.rb')
describe ScheduleFixGitlabComPagesAccessLevel, :migration, :sidekiq, schema: 2019_10_16_072826 do describe ScheduleFixGitlabComPagesAccessLevel, :migration, :sidekiq_might_not_need_inline, schema: 2019_10_16_072826 do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
let(:migration_name) { 'FixGitlabComPagesAccessLevel' } let(:migration_name) { 'FixGitlabComPagesAccessLevel' }
......
...@@ -15,7 +15,7 @@ describe FromUnion do ...@@ -15,7 +15,7 @@ describe FromUnion do
it 'selects from the results of the UNION' do it 'selects from the results of the UNION' do
query = model.from_union([model.where(id: 1), model.where(id: 2)]) query = model.from_union([model.where(id: 1), model.where(id: 2)])
expect(query.to_sql).to match(/FROM \(SELECT.+UNION.+SELECT.+\) users/m) expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\nUNION\n\(SELECT.+\)\) users/m)
end end
it 'supports the use of a custom alias for the sub query' do it 'supports the use of a custom alias for the sub query' do
...@@ -24,7 +24,7 @@ describe FromUnion do ...@@ -24,7 +24,7 @@ describe FromUnion do
alias_as: 'kittens' alias_as: 'kittens'
) )
expect(query.to_sql).to match(/FROM \(SELECT.+UNION.+SELECT.+\) kittens/m) expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\nUNION\n\(SELECT.+\)\) kittens/m)
end end
it 'supports keeping duplicate rows' do it 'supports keeping duplicate rows' do
...@@ -34,7 +34,7 @@ describe FromUnion do ...@@ -34,7 +34,7 @@ describe FromUnion do
) )
expect(query.to_sql) expect(query.to_sql)
.to match(/FROM \(SELECT.+UNION ALL.+SELECT.+\) users/m) .to match(/FROM \(\(SELECT.+\)\nUNION ALL\n\(SELECT.+\)\) users/m)
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment