diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 18:18:33 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 18:18:33 +0000 |
commit | f64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch) | |
tree | a2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /doc/development | |
parent | bfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff) | |
download | gitlab-ce-f64a639bcfa1fc2bc89ca7db268f594306edfd7c.tar.gz |
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'doc/development')
110 files changed, 22162 insertions, 3884 deletions
diff --git a/doc/development/README.md b/doc/development/README.md index 3d5335feb11..43ceb737dde 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -261,7 +261,7 @@ See [database guidelines](database/index.md). ## Product Intelligence guides - [Product Intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) -- [Usage Ping guide](usage_ping.md) +- [Usage Ping guide](usage_ping/index.md) - [Snowplow guide](snowplow.md) ## Experiment guide @@ -287,6 +287,7 @@ See [database guidelines](database/index.md). ## Domain-specific guides - [CI/CD development documentation](cicd/index.md) +- [AppSec development documentation](appsec/index.md) ## Other Development guides diff --git a/doc/development/agent/user_stories.md b/doc/development/agent/user_stories.md index 609be47a3cb..ab135cad9d3 100644 --- a/doc/development/agent/user_stories.md +++ b/doc/development/agent/user_stories.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Kubernetes Agent user stories **(PREMIUM SELF)** -The [personas in action](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#user-personas) +The [personas in action](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#user-personas) for the Kubernetes Agent are: - [Sasha, the Software Developer](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#sasha-software-developer). diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md index 85098689392..8bac02c99af 100644 --- a/doc/development/api_graphql_styleguide.md +++ b/doc/development/api_graphql_styleguide.md @@ -13,7 +13,7 @@ This document outlines the style guide for the GitLab [GraphQL API](../api/graph <!-- vale gitlab.Spelling = NO --> We use the [GraphQL Ruby gem](https://graphql-ruby.org/) written by [Robert Mosolgo](https://github.com/rmosolgo/). <!-- vale gitlab.Spelling = YES --> -In addition, we have a subscription to [GraphQL Pro](https://www.graphql.pro). For details see [GraphQL Pro subscription](graphql_guide/graphql_pro.md). +In addition, we have a subscription to [GraphQL Pro](https://graphql.pro/). For details see [GraphQL Pro subscription](graphql_guide/graphql_pro.md). All GraphQL queries are directed to a single endpoint ([`app/controllers/graphql_controller.rb#execute`](https://gitlab.com/gitlab-org/gitlab/blob/master/app%2Fcontrollers%2Fgraphql_controller.rb)), @@ -76,6 +76,28 @@ Rake task. Requests time out at 30 seconds. +## Breaking changes + +The GitLab GraphQL API is [versionless](https://graphql.org/learn/best-practices/#versioning) which means +developers must familiarize themselves with our [deprecation cycle of breaking changes](#breaking-changes). + +Breaking changes are: + +- 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 +discussed in [Nullable fields](#nullable-fields). +- Changing an argument from being optional (`required: false`) to being required (`required: true`). +- Changing the [max page size](#page-size-limit) of a connection. +- Lowering the global limits for query complexity and depth. +- Anything else that can result in queries hitting a limit that previously was allowed. + +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. + ## Global IDs The GitLab GraphQL API uses Global IDs (i.e: `"gid://gitlab/MyObject/123"`) @@ -448,7 +470,7 @@ fails. Consider this when toggling the visibility of the feature on or off on production. The `feature_flag` property does not allow the use of -[feature gates based on actors](../development/feature_flags/development.md). +[feature gates based on actors](../development/feature_flags/index.md). This means that the feature flag cannot be toggled only for particular projects, groups, or users, but instead can only be toggled globally for everyone. @@ -490,15 +512,18 @@ def foo end ``` -## Deprecating fields and enum values +## Deprecating fields, arguments, and enum values The GitLab GraphQL API is versionless, which means we maintain backwards -compatibility with older versions of the API with every change. Rather -than removing a field or [enum value](#enums), we need to _deprecate_ it instead. +compatibility with older versions of the API with every change. + +Rather than removing fields, arguments, or [enum values](#enums), they +must be _deprecated_ instead. + The deprecated parts of the schema can then be removed in a future release -in accordance with the [GitLab deprecation process](../api/graphql/index.md#deprecation-process). +in accordance with the [GitLab deprecation process](../api/graphql/index.md#deprecation-and-removal-process). -Fields and enum values are deprecated using the `deprecated` property. +Fields, arguments, and enum values are deprecated using the `deprecated` property. The value of the property is a `Hash` of: - `reason` - Reason for the deprecation. @@ -518,14 +543,15 @@ is appended to the `description`. ### Deprecation reason style guide -Where the reason for deprecation is due to the field or enum value being -replaced, the `reason` must be: +Where the reason for deprecation is due to the field, argument, or enum value being +replaced, the `reason` must indicate the replacement. For example, the +following is a `reason` for a replaced field: ```plaintext Use `otherFieldName` ``` -Example: +Examples: ```ruby field :designs, ::Types::DesignManagement::DesignCollectionType, null: true, @@ -544,8 +570,8 @@ module Types end ``` -If the field is not being replaced by another field, a descriptive -deprecation `reason` should be given. +If the field, argument, or enum value being deprecated is not being replaced, +a descriptive deprecation `reason` should be given. See also [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations). @@ -594,7 +620,7 @@ end ``` Enum values can be deprecated using the -[`deprecated` keyword](#deprecating-fields-and-enum-values). +[`deprecated` keyword](#deprecating-fields-arguments-and-enum-values). ### Defining GraphQL enums dynamically from Rails enums @@ -1567,7 +1593,7 @@ mount_aliased_mutation 'BarMutation', Mutations::FooMutation ``` This allows us to rename a mutation and continue to support the old name, -when coupled with the [`deprecated`](#deprecating-fields-and-enum-values) +when coupled with the [`deprecated`](#deprecating-fields-arguments-and-enum-values) argument. Example: diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md index 3608636dd55..c42e9224105 100644 --- a/doc/development/application_limits.md +++ b/doc/development/application_limits.md @@ -139,14 +139,14 @@ end Self-managed: -- `default` - Everyone +- `default`: Everyone. GitLab.com: -- `default` - Any system-wide feature -- `free` - Namespaces and projects with a Free subscription -- `bronze`- Namespaces and projects with a Bronze subscription -- `silver` - Namespaces and projects with a Silver subscription -- `gold` - Namespaces and projects with a Gold subscription +- `default`: Any system-wide feature. +- `free`: Namespaces and projects with a Free subscription. +- `bronze`: Namespaces and projects with a Bronze subscription. This tier is no longer available for purchase. +- `silver`: Namespaces and projects with a Premium subscription. +- `gold`: Namespaces and projects with an Ultimate subscription. The `test` environment doesn't have any plans. diff --git a/doc/development/appsec/index.md b/doc/development/appsec/index.md new file mode 100644 index 00000000000..e8ce885e75d --- /dev/null +++ b/doc/development/appsec/index.md @@ -0,0 +1,32 @@ +--- +stage: Secure, Protect +group: all +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 +type: index, dev, reference +--- + +# Application Security development documentation + +Development guides that are specific to the stages that work on Application Security features are listed here. + +Please go to [Application Security](../../user/application_security/index.md) if you are looking for documentation on how to use those features. + +## Namespaces + +Application Security code in the Rails monolith is organized into the following namespaces, which generally follows +the feature categories in the [Secure](https://about.gitlab.com/stages-devops-lifecycle/secure/) and [Protect](https://about.gitlab.com/stages-devops-lifecycle/protect/) stages. + +- `AppSec`: shared code. + - `AppSec::ContainerScanning`: Container Scanning code. + - `AppSec::Dast`: DAST code. + - `AppSec::DependencyScanning`: Dependency Scanning code. + - `AppSec::Fuzzing::Api`: API Fuzzing code. + - `AppSec::Fuzzing::Coverage`: Coverage Fuzzing code. + - `AppSec::Fuzzing`: Shared fuzzing code. + - `AppSec::LicenseCompliance`: License Compliance code. + - `AppSec::Sast`: SAST code. + - `AppSec::SecretDetection`: Secret Detection code. + - `AppSec::VulnMgmt`: Vulnerability Management code. + +Most AppSec code does not conform to these namespace guidelines. When developing, make an effort +to move existing code into the appropriate namespace whenever possible. diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 69055131ae8..5564d0722b0 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -224,17 +224,7 @@ Component statuses are linked to configuration documentation for each component. ### Component list -Table description links: - -- [Omnibus GitLab](https://docs.gitlab.com/omnibus/) -- [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) -- [GitLab chart](https://docs.gitlab.com/charts/) -- [Minikube Minimal](https://docs.gitlab.com/charts/development/minikube/#deploying-gitlab-with-minimal-settings) -- [GitLab.com](https://gitlab.com) -- [Source](../install/installation.md) -- [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) - -| Component | Description | Omnibus GitLab | GitLab Environment Toolkit (GET) | GitLab chart | Minikube Minimal | GitLab.com | Source | GDK | CE/EE | +| Component | Description | [Omnibus GitLab](https://docs.gitlab.com/omnibus/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) | [GitLab chart](https://docs.gitlab.com/charts/) | [Minikube Minimal](https://docs.gitlab.com/charts/development/minikube/#deploying-gitlab-with-minimal-settings) | [GitLab.com](https://gitlab.com) | [Source](../install/installation.md) | [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) | [CE/EE](https://about.gitlab.com/install/ce-or-ee/) | |-------------------------------------------------------|----------------------------------------------------------------------|:--------------:|:--------------:|:------------:|:----------------:|:----------:|:------:|:---:|:-------:| | [Certificate Management](#certificate-management) | TLS Settings, Let's Encrypt | ✅ | ✅ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE & EE | | [Consul](#consul) | Database node discovery, failover | ⚙ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | EE Only | @@ -332,7 +322,7 @@ Consul is a tool for service discovery and configuration. Consul is distributed, - Configuration: - [Omnibus](https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration) - [Charts](https://docs.gitlab.com/charts/charts/gitlab/migrations/) - - [Source](../update/upgrading_from_source.md#14-install-libraries-migrations-etc) + - [Source](../update/upgrading_from_source.md#10-install-libraries-migrations-etc) - Layer: Core Service (Data) #### Elasticsearch @@ -651,7 +641,7 @@ Redis is packaged to provide a place to store: - [Project page](https://github.com/docker/distribution/blob/master/README.md) - Configuration: - - [Omnibus](../update/upgrading_from_source.md#14-install-libraries-migrations-etc) + - [Omnibus](../update/upgrading_from_source.md#10-install-libraries-migrations-etc) - [Charts](https://docs.gitlab.com/charts/charts/registry/) - [Source](../administration/packages/container_registry.md#enable-the-container-registry) - [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/registry.md) @@ -909,7 +899,7 @@ in Rails, scheduled to run whenever an SSH key is modified by a user. instead of keys. In this case, `AuthorizedKeysCommand` is replaced with an `AuthorizedPrincipalsCommand`. This extracts a username from the certificate without using the Rails internal API, which is used instead of `key_id` in the -`/api/internal/allowed` call later. +[`/api/internal/allowed`](internal_api.md) call later. GitLab Shell also has a few operations that do not involve Gitaly, such as resetting two-factor authentication codes. These are handled in the same way, diff --git a/doc/development/auto_devops.md b/doc/development/auto_devops.md index eaf1d712f17..c127858d3e7 100644 --- a/doc/development/auto_devops.md +++ b/doc/development/auto_devops.md @@ -47,12 +47,12 @@ found in ## Development environment -Configuring [GDK for Auto -DevOps](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/auto_devops.md). +See the [Simple way to develop/test Kubernetes workflows with a local cluster](https://gitlab.com/gitlab-org/gitlab-development-kit/-/issues/1064) +issue for discussion around setting up Auto DevOps development environments. ## Monitoring on GitLab.com The metric -[`auto_devops_completed_pipelines_total`](https://thanos-query.ops.gitlab.net/graph?g0.range_input=72h&g0.max_source_resolution=0s&g0.expr=sum(increase(auto_devops_pipelines_completed_total%7Benvironment%3D%22gprd%22%7D%5B60m%5D))%20by%20(status)&g0.tab=0) +[`auto_devops_completed_pipelines_total`](https://thanos.gitlab.net/graph?g0.range_input=72h&g0.max_source_resolution=0s&g0.expr=sum(increase(auto_devops_pipelines_completed_total%7Benvironment%3D%22gprd%22%7D%5B60m%5D))%20by%20(status)&g0.tab=0) (only available to GitLab team members) counts completed Auto DevOps pipelines, labeled by status. diff --git a/doc/development/build_test_package.md b/doc/development/build_test_package.md index 421ee5d0c84..1506017c6d5 100644 --- a/doc/development/build_test_package.md +++ b/doc/development/build_test_package.md @@ -40,7 +40,7 @@ used to trigger the build. In scenarios where a configuration change is to be introduced and Omnibus GitLab repository already has the necessary changes in a specific branch, you can build -a package against that branch through an environment variable named -`OMNIBUS_BRANCH`. To do this, specify that environment variable with the name of +a package against that branch through a CI/CD variable named +`OMNIBUS_BRANCH`. To do this, specify that variable with the name of the branch as value in `.gitlab-ci.yml` and push a commit. This will create a manual job that can be used to trigger the build. diff --git a/doc/development/changelog.md b/doc/development/changelog.md index f2c8aa4db62..98a3e75bb3c 100644 --- a/doc/development/changelog.md +++ b/doc/development/changelog.md @@ -45,7 +45,7 @@ the `author` field. GitLab team members **should not**. **must** have a changelog entry, without `merge_request` value and with `type` set to `security`. - Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content. -- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry. This includes modifying complexity of GraphQL fields. +- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry. See the [complete list what comprises a GraphQL breaking change](api_graphql_styleguide.md#breaking-changes). - Performance improvements **should** have a changelog entry. - Changes that need to be documented in the Product Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary) also require a changelog entry. @@ -57,8 +57,7 @@ the `author` field. GitLab team members **should not**. - Any change behind an enabled feature flag **should** have a changelog entry. - Any change that adds new usage data metrics and changes that needs to be documented in Product Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary) **should** have a changelog entry. - A change that adds snowplow events **should** have a changelog entry - -- A change that [removes a feature flag](feature_flags/development.md) **should** have a changelog entry - - only if the feature flag did not default to true already. +- A change that [removes a feature flag](feature_flags/index.md) **must** have a changelog entry. - A fix for a regression introduced and then fixed in the same release (i.e., fixing a bug introduced during a monthly release candidate) **should not** have a changelog entry. diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md index 0341abf5eeb..4ae49103d1b 100644 --- a/doc/development/chatops_on_gitlabcom.md +++ b/doc/development/chatops_on_gitlabcom.md @@ -61,4 +61,4 @@ To request access to ChatOps on GitLab.com: - [ChatOps Usage](../ci/chatops/index.md) - [Understanding EXPLAIN plans](understanding_explain_plans.md) -- [Feature Groups](feature_flags/development.md#feature-groups) +- [Feature Groups](feature_flags/index.md#feature-groups) diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md index 94b03634e25..ed0d217c247 100644 --- a/doc/development/cicd/templates.md +++ b/doc/development/cicd/templates.md @@ -47,7 +47,7 @@ performance: ``` and users include this template with passing an argument to the `performance` job. -This can be done by specifying the environment variable `TARGET_URL` in _their_ `.gitlab-ci.yml`: +This can be done by specifying the CI/CD variable `TARGET_URL` in _their_ `.gitlab-ci.yml`: ```yaml include: @@ -72,6 +72,10 @@ Please read [versioning](#versioning) section for introducing breaking change sa When a root `.gitlab-ci.yml` [includes](../../ci/yaml/README.md#include) multiple templates, these global keywords could be overridden by the others and cause an unexpected behavior. +- Include [a changelog](../changelog.md) if your merge request introduces a user-facing change. +- Use [`$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH`](../../ci/variables/predefined_variables.md) + instead of a hardcoded `main` branch, and never use `master`. +- Use [`rules`](../../ci/yaml/README.md#rules) instead of [`only` or `except`](../../ci/yaml/README.md#onlyexcept-basic), if possible. ## Versioning @@ -88,7 +92,7 @@ for example `Jobs/Deploy.gitlab-ci.yml`. You can make a new stable template by copying [the latest template](#latest-version) available in a major milestone release of GitLab like `13.0`. All breaking changes must be announced in a blog post before the official release, for example -[GitLab.com is moving to 13.0, with narrow breaking changes](https://about.gitlab.com/releases/2020/05/06/gitlab-com-13-0-breaking-changes/) +[GitLab.com is moving to 13.0, with narrow breaking changes](https://about.gitlab.com/blog/2020/05/06/gitlab-com-13-0-breaking-changes/) You can change a stable template version in a minor GitLab release like `13.1` if: @@ -180,7 +184,7 @@ is updated in a major version GitLab release. ## Security A template could contain malicious code. For example, a template that contains the `export` shell command in a job -might accidentally expose project secret variables in a job log. +might accidentally expose secret project CI/CD variables in a job log. If you're unsure if it's secure or not, you need to ask security experts for cross-validation. ## Contribute CI/CD Template Merge Requests diff --git a/doc/development/code_intelligence/index.md b/doc/development/code_intelligence/index.md index ac962e3ae3e..790ba1539b7 100644 --- a/doc/development/code_intelligence/index.md +++ b/doc/development/code_intelligence/index.md @@ -1,6 +1,6 @@ --- stage: Create -group: Source Code +group: Code Review 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 --- diff --git a/doc/development/code_review.md b/doc/development/code_review.md index dada6adcce7..0a811ceba65 100644 --- a/doc/development/code_review.md +++ b/doc/development/code_review.md @@ -70,16 +70,16 @@ It picks reviewers and maintainers from the list at the [engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page, with these behaviors: -1. It doesn't pick people whose Slack or [GitLab status](../user/profile/index.md#current-status): +1. It doesn't pick people whose Slack or [GitLab status](../user/profile/index.md#set-your-current-status): - contains the string 'OOO', 'PTO', 'Parental Leave', or 'Friends and Family' - emoji is `:palm_tree:`, `:beach:`, `:beach_umbrella:`, `:beach_with_umbrella:`, `:ferris_wheel:`, `:thermometer:`, `:face_with_thermometer:`, `:red_circle:`, `:bulb:`, `:sun_with_face:`. 1. [Trainee maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer) are three times as likely to be picked as other reviewers. -1. Team members whose Slack or [GitLab status](../user/profile/index.md#current-status) emoji +1. Team members whose Slack or [GitLab status](../user/profile/index.md#set-your-current-status) emoji is 🔵 `:large_blue_circle:` are more likely to be picked. This applies to both reviewers and trainee maintainers. - Reviewers with `:large_blue_circle:` are two times as likely to be picked as other reviewers. - Trainee maintainers with `:large_blue_circle:` are four times as likely to be picked as other reviewers. -1. People whose [GitLab status](../user/profile/index.md#current-status) emoji +1. People whose [GitLab status](../user/profile/index.md#set-your-current-status) emoji is 🔶 `:large_orange_diamond:` are half as likely to be picked. This applies to both reviewers and trainee maintainers. 1. It always picks the same reviewers and maintainers for the same branch name (unless their OOO status changes, as in point 1). It @@ -283,6 +283,8 @@ first time. you forget to remove any debugging code? - Consider providing instructions on how to test the merge request. This can be helpful for reviewers not familiar with the product feature or area of the codebase. +- If you know your change depends on another being merged first, note it in the + description and set an [merge request dependency](../user/project/merge_requests/merge_request_dependencies.md). - Be grateful for the reviewer's suggestions. (`Good call. I'll make that change.`) - Don't take it personally. The review is of the code, not of you. - Explain why the code exists. ("It's like that because of these reasons. Would @@ -345,6 +347,8 @@ experience, refactors the existing code). Then: - For non-mandatory suggestions, decorate with (non-blocking) so the author knows they can optionally resolve within the merge request or follow-up at a later stage. - There's a [Chrome/Firefox add-on](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes. +- Ensure there are no open dependencies. Check [related issues](../user/project/issues/related_issues.md) for blockers. Clarify with the author(s) +if necessary. If blocked by one or more open MRs, set an [MR dependency](../user/project/merge_requests/merge_request_dependencies.md). - After a round of line notes, it can be helpful to post a summary note such as "Looks good to me", or "Just a couple things to address." - Assign the merge request to the author if changes are required following your @@ -390,6 +394,8 @@ When ready to merge: - **Start a new merge request pipeline with the `Run Pipeline` button in the merge request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).** Note that: + - If **[master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master), + do not merge the merge request**. Follow these specific [handbook instructions](https://about.gitlab.com/handbook/engineering/workflow/#maintaining-throughput-during-broken-master). - If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you might merge without starting a new pipeline as the merge request is close enough to `master`. @@ -397,10 +403,6 @@ When ready to merge: Before triggering the pipeline, review all changes for **malicious code**. If you cannot trigger the pipeline, review the status of the fork relative to `master`. If it's more than 100 commits behind, ask the author to rebase it before merging. - - If [master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master), - in addition to the two above rules, check that any failure also happens - in `master` and post a link to the ~"master:broken" issue before clicking the - red "Merge" button. - When you set the MR to "Merge When Pipeline Succeeds", you should take over subsequent revisions for anything that would be spotted after that. diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md index da38d1e73b4..7029c8a8384 100644 --- a/doc/development/contributing/issue_workflow.md +++ b/doc/development/contributing/issue_workflow.md @@ -149,8 +149,8 @@ and `~"group::knowledge"` is picked up by someone in the Access group of the Pla the issue should be relabeled as `~"group::access"` while keeping the original `~"devops::create"` unchanged. -We also use stage and group labels to help quantify our [throughput](https://about.gitlab.com/handbook/engineering/management/throughput/). -Please read [Stage and Group labels in Throughput](https://about.gitlab.com/handbook/engineering/management/throughput/#stage-and-group-labels-in-throughput) for more information on how the labels are used in this context. +We also use stage and group labels to help measure our [merge request rates](https://about.gitlab.com/handbook/engineering/merge-request-rate/). +Please read [Stage and Group labels](https://about.gitlab.com/handbook/engineering/metrics/#stage-and-group-labels) for more information on how the labels are used in this context. ### Category labels @@ -181,7 +181,7 @@ For instance, the "DevOps Report" category is represented by the `devops_reports.name` value is "DevOps Reports". If a category's label doesn't respect this naming convention, it should be specified -with [the `label` attribute](https://about.gitlab.com/handbook/marketing/website/#category-attributes) +with [the `label` attribute](https://about.gitlab.com/handbook/marketing/inbound-marketing/digital-experience/website/#category-attributes) in <https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml>. ### Feature labels diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md index 166f7b350bf..9051b621bcd 100644 --- a/doc/development/contributing/merge_request_workflow.md +++ b/doc/development/contributing/merge_request_workflow.md @@ -68,10 +68,11 @@ request is as follows: 1. Use the syntax `Solves #XXX`, `Closes #XXX`, or `Refs #XXX` to mention the issue(s) your merge request addresses. Referenced issues do not [close automatically](../../user/project/issues/managing_issues.md#closing-issues-automatically). You must close them manually once the merge request is merged. + 1. The MR must include *Before* and *After* screenshots if UI changes are made. + 1. Include any steps or setup required to ensure reviewers can view the changes you've made (e.g. include any information about feature flags). 1. If you're allowed to, set a relevant milestone and [labels](issue_workflow.md). 1. UI changes should use available components from the GitLab Design System, - [Pajamas](https://design.gitlab.com/). The MR must include *Before* and - *After* screenshots. + [Pajamas](https://design.gitlab.com/). 1. If the MR changes CSS classes, please include the list of affected pages, which can be found by running `grep css-class ./app -R`. 1. If your MR touches code that executes shell commands, reads or opens files, or diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md index 2a2cfebe964..444a067a780 100644 --- a/doc/development/contributing/style_guides.md +++ b/doc/development/contributing/style_guides.md @@ -56,10 +56,10 @@ The current Lefthook configuration can be found in [`lefthook.yml`](https://gitl Before you push your changes, Lefthook automatically runs the following checks: - Danger: Runs a subset of checks that `danger-review` runs on your merge requests. -- ES lint: Run `yarn eslint` checks (with the [`.eslintrc.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.eslintrc.yml) configuration) on the modified `*.{js,vue}` files. Tags: `frontend`, `style`. +- ES lint: Run `yarn run lint:eslint` checks (with the [`.eslintrc.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.eslintrc.yml) configuration) on the modified `*.{js,vue}` files. Tags: `frontend`, `style`. - HAML lint: Run `bundle exec haml-lint` checks (with the [`.haml-lint.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.haml-lint.yml) configuration) on the modified `*.html.haml` files. Tags: `view`, `haml`, `style`. - Markdown lint: Run `yarn markdownlint` checks on the modified `*.md` files. Tags: `documentation`, `style`. -- SCSS lint: Run `bundle exec scss-lint` checks (with the [`.scss-lint.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.scss-lint.yml) configuration) on the modified `*.scss{,.css}` files. Tags: `stylesheet`, `css`, `style`. +- SCSS lint: Run `yarn lint:stylelint` checks (with the [`.stylelintrc`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.stylelintrc) configuration) on the modified `*.scss{,.css}` files. Tags: `stylesheet`, `css`, `style`. - RuboCop: Run `bundle exec rubocop` checks (with the [`.rubocop.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.rubocop.yml) configuration) on the modified `*.rb` files. Tags: `backend`, `style`. - Vale: Run `vale` checks (with the [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini) configuration) on the modified `*.md` files. Tags: `documentation`, `style`. @@ -146,7 +146,7 @@ One way to generate the initial list is to run the `todo` auto generation, with `exclude limit` set to a high number. ```shell -bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit=10000 +bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit=100000 ``` You can then move the list from the freshly generated `.rubocop_todo.yml` for the Cop being actively @@ -154,6 +154,16 @@ resolved and place it in the `.rubocop_manual_todo.yml`. In this scenario, do no changes to the `.rubocop_todo.yml` as an `exclude limit` that is higher than 15 will make the `.rubocop_todo.yml` hard to parse. +### Reveal existing RuboCop exceptions + +To reveal existing RuboCop exceptions in the code that have been excluded via `.rubocop_todo.yml` and +`.rubocop_manual_todo.yml`, set the environment variable `REVEAL_RUBOCOP_TODO` to `1`. + +This allows you to reveal existing RuboCop exceptions during your daily work cycle and fix them along the way. + +NOTE: +Permanent `Exclude`s should be defined in `.rubocop.yml` instead of `.rubocop_manual_todo.yml`. + ## Database migrations See the dedicated [Database Migrations Style Guide](../migration_style_guide.md). diff --git a/doc/development/database/client_side_connection_pool.md b/doc/development/database/client_side_connection_pool.md index 1a30d2d73a3..8316a75ac8d 100644 --- a/doc/development/database/client_side_connection_pool.md +++ b/doc/development/database/client_side_connection_pool.md @@ -43,7 +43,7 @@ hardcoded value (10). At this point, we need to investigate what is using more connections than we anticipated. To do that, we can use the `gitlab_ruby_threads_running_threads` metric. For example, [this -graph](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0) +graph](https://thanos.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0) shows all running threads that connect to the database by their name. Threads labeled `puma worker` or `sidekiq_worker_thread` are the threads that define `Gitlab::Runtime.max_threads` so those are diff --git a/doc/development/database/index.md b/doc/development/database/index.md index 367ef455898..870ae1542bd 100644 --- a/doc/development/database/index.md +++ b/doc/development/database/index.md @@ -69,3 +69,4 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Miscellaneous - [Maintenance operations](maintenance_operations.md) +- [Update multiple database objects](setting_multiple_values.md) diff --git a/doc/development/database/setting_multiple_values.md b/doc/development/database/setting_multiple_values.md index 54870380047..0f23aae9f79 100644 --- a/doc/development/database/setting_multiple_values.md +++ b/doc/development/database/setting_multiple_values.md @@ -4,24 +4,22 @@ group: Database 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 --- -# Setting Multiple Values +# Update multiple database objects > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32921) in GitLab 13.5. -There's often a need to update multiple objects with new values for one -or more columns. One method of doing this is using `Relation#update_all`: +You can update multiple database objects with new values for one or more columns. +One method is to use `Relation#update_all`: ```ruby user.issues.open.update_all(due_date: 7.days.from_now) # (1) user.issues.update_all('relative_position = relative_position + 1') # (2) ``` -But what do you do if you cannot express the update as either a static value (1) -or as a calculation (2)? - -Thankfully we can use `UPDATE FROM` to express the need to update multiple rows -with distinct values in a single query. One can either use a temporary table, or -a Common Table Expression (CTE), and then use that as the source of the updates: +If you cannot express the update as either a static value (1) or as a calculation (2), +use `UPDATE FROM` to express the need to update multiple rows with distinct values +in a single query. Create a temporary table, or a Common Table Expression (CTE), +and use it as the source of the updates: ```sql with updates(obj_id, new_title, new_weight) as ( @@ -34,23 +32,22 @@ update issues where id = obj_id ``` -The bad news: there is no way to express this in ActiveRecord or even dropping -down to ARel. The `UpdateManager` does not support `update from`, so this -is not expressible. - -The good news: we supply an abstraction to help you generate these kinds of -updates, called `Gitlab::Database::BulkUpdate`. This constructs queries such as the -above, and uses binding parameters to avoid SQL injection. +You can't express this in ActiveRecord, or by dropping down to [Arel](https://api.rubyonrails.org/v6.1.0/classes/Arel.html), +because the `UpdateManager` does not support `update from`. However, we supply +an abstraction to help you generate these kinds of updates: `Gitlab::Database::BulkUpdate`. +This abstraction constructs queries like the previous example, and uses +binding parameters to avoid SQL injection. ## Usage -To use this, we need: +To use `Gitlab::Database::BulkUpdate`, we need: -- the list of columns to update -- a mapping from object/ID to the new values to set for that object -- a way to determine the table for each object +- The list of columns to update. +- A mapping from the object (or ID) to the new values to set for that object. +- A way to determine the table for each object. -For example, we can express the query above as: +For example, we can express the example query in a way that determines the +table by calling `object.class.table_name`: ```ruby issue_a = Issue.find(..) @@ -63,10 +60,7 @@ issue_b = Issue.find(..) }) ``` -Here the table can be determined automatically, from calling -`object.class.table_name`, so we don't need to provide anything. - -We can even pass heterogeneous sets of objects, if the updates all make sense +You can even pass heterogeneous sets of objects, if the updates all make sense for them: ```ruby @@ -82,8 +76,8 @@ merge_request = MergeRequest.find(..) }) ``` -If your objects do not return the correct model class (perhaps because they are -part of a union), then we need to specify this explicitly in a block: +If your objects do not return the correct model class, such as if they are part +of a union, then specify the model class explicitly in a block: ```ruby bazzes = params @@ -103,7 +97,10 @@ end ## Caveats -Note that this is a **very low level** tool, and operates on the raw column -values. Enumerations and state fields must be translated into their underlying -representations, for example, and nested associations are not supported. No -validations or hooks are called. +This tool is **very low level**, and operates directly on the raw column +values. You should consider these issues if you implement it: + +- Enumerations and state fields must be translated into their underlying + representations. +- Nested associations are not supported. +- No validations or hooks are called. diff --git a/doc/development/database_query_comments.md b/doc/development/database_query_comments.md index 8a5abad3815..39b14074073 100644 --- a/doc/development/database_query_comments.md +++ b/doc/development/database_query_comments.md @@ -39,24 +39,11 @@ Examples of queries with comments as observed in `development.log`: 1. Rails: ```sql - SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = $1 LIMIT $2 [["project_id", 5], ["LIMIT", 1]] /*application:web,controller:jobs,action:trace,correlation_id:rYF4mey9CH3,line:/app/policies/project_policy.rb:504:in `feature_available?'*/ + /*application:web,controller:jobs,action:trace,correlation_id:rYF4mey9CH3,line:/app/policies/project_policy.rb:504:in `feature_available?'*/ SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = $1 LIMIT $2 [["project_id", 5], ["LIMIT", 1]] ``` 1. Sidekiq: ```sql - SELECT "ci_pipelines".* FROM "ci_pipelines" WHERE "ci_pipelines"."id" = $1 LIMIT $2 [["id", 64], ["LIMIT", 1]] /*application:sidekiq,jid:e7d6668a39a991e323009833,job_class:ExpireJobCacheWorker,correlation_id:rYF4mey9CH3,line:/app/workers/expire_job_cache_worker.rb:14:in `perform'*/ + /*application:sidekiq,jid:e7d6668a39a991e323009833,job_class:ExpireJobCacheWorker,correlation_id:rYF4mey9CH3,line:/app/workers/expire_job_cache_worker.rb:14:in `perform'*/ SELECT "ci_pipelines".* FROM "ci_pipelines" WHERE "ci_pipelines"."id" = $1 LIMIT $2 [["id", 64], ["LIMIT", 1]] ``` - -## Enable/Disable the feature - -Enabling or disabling the feature requires a **restart/SIGHUP** of the Web and -Sidekiq workers, as the feature flag's state is memoized upon starting up. - -The `feature_flag` for this feature is **disabled** by default. You can enable -or disable it with: - -```ruby -Feature.enable(:marginalia) -Feature.disable(:marginalia) -``` diff --git a/doc/development/directory_structure.md b/doc/development/directory_structure.md index c2329feb941..c96e2cc3254 100644 --- a/doc/development/directory_structure.md +++ b/doc/development/directory_structure.md @@ -34,3 +34,61 @@ module MyDomain end end ``` + +### About namespace naming + +A good guideline for naming a top-level namespace (bounded context) is to use the related +feature category. For example, `Continuous Integration` feature category maps to `Ci::` namespace. + +Alternatively a new class could be added to `Projects::` or `Groups::` if it's either: + +- Strictly related to one of these domains. For example `Projects::Alias`. +- A new component that does not have yet a more specific domain. In this case, when + a more explicit domain does emerge we would need to move the class to a more specific + namespace. + +Do not use the [stage or group name](https://about.gitlab.com/handbook/product/categories/#devops-stages) +since a feature category could be reassigned to a different group in the future. + +```ruby +# bad +module Create + class Commit + end +end + +# good +module Repositories + class Commit + end +end +``` + +On the other hand, a feature category may sometimes be too granular. Features tend to be +treated differently according to Product and Marketing, while they may share a lot of +domain models and behavior under the hood. In this case, having too many bounded contexts +could make them shallow and more coupled with other contexts. + +Bounded contexts (or top-level namespaces) can be seen as macro-components in the overall app. +Good bounded contexts should be [deep](https://medium.com/@nakabonne/depth-of-module-f62dac3c2fdb) +so consider having nested namespaces to further break down complex parts of the domain. +E.g. `Ci::Config::`. + +For example, instead of having separate and granular bounded contexts like: `ContainerScanning::`, +`ContainerHostSecurity::`, `ContainerNetworkSecurity::`, we could have: + +```ruby +module ContainerSecurity + module HostSecurity + end + + module NetworkSecurity + end + + module Scanning + end +end +``` + +If classes that are defined into a namespace have a lot in common with classes in other namespaces, +chances are that these two namespaces are part of the same bounded context. diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md index eb20e721e46..17967c5f63c 100644 --- a/doc/development/distributed_tracing.md +++ b/doc/development/distributed_tracing.md @@ -206,7 +206,7 @@ If `GITLAB_TRACING` is not configured correctly, this issue is logged: By default, GitLab ships with the Jaeger tracer, but other tracers can be included at compile time. Details of how this can be done are included in the [LabKit tracing -documentation](https://godoc.org/gitlab.com/gitlab-org/labkit/tracing). +documentation](https://pkg.go.dev/gitlab.com/gitlab-org/labkit/tracing). If no log messages about tracing are emitted, the `GITLAB_TRACING` environment variable is likely not set. diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md index c9c291abd2c..8fe3f0cbf8e 100644 --- a/doc/development/documentation/feature_flags.md +++ b/doc/development/documentation/feature_flags.md @@ -14,9 +14,13 @@ feature flag depends on its state (enabled or disabled). When the state changes, the developer who made the change **must update the documentation** accordingly. +Every feature introduced to the codebase, even if it's behind a feature flag, +must be documented. For context, see the +[latest merge request that updated this guideline](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47917#note_459984428). + ## Criteria -According to the process of [deploying GitLab features behind feature flags](../feature_flags/process.md): +According to the process of [deploying GitLab features behind feature flags](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle): > - _By default, feature flags should be off._ > - _Feature flags should remain in the codebase for a short period as possible to reduce the need for feature flag accounting._ diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md index 92fd17f9d3e..70fa80b3306 100644 --- a/doc/development/documentation/site_architecture/index.md +++ b/doc/development/documentation/site_architecture/index.md @@ -118,7 +118,7 @@ If you change the Dockerfile configuration and rebuild the images, you can break pipeline in the main `gitlab` repository as well as in `gitlab-docs`. Create an image with a different name first and test it to ensure you do not break the pipelines. -1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI / CD > Pipelines**. +1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Pipelines**. 1. Click the **Run Pipeline** button. 1. See that a new pipeline is running. The jobs that build the images are in the first stage, `build-images`. You can click the pipeline number to see the larger pipeline @@ -137,7 +137,7 @@ and deploys it to <https://docs.gitlab.com>. If you need to build and deploy the site immediately (must have maintainer level permissions): -1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI / CD > Schedules**. +1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Schedules**. 1. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, click the **play** (**{play}**) button. Read more about the [deployment process](deployment_process.md). diff --git a/doc/development/documentation/site_architecture/release_process.md b/doc/development/documentation/site_architecture/release_process.md index ba5363dbb71..7bdf3fbdcf8 100644 --- a/doc/development/documentation/site_architecture/release_process.md +++ b/doc/development/documentation/site_architecture/release_process.md @@ -4,191 +4,165 @@ group: unassigned 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 --- -# GitLab Docs monthly release process +# Monthly release process -When a new GitLab version is released on the 22nd, we need to create the respective -single Docker image, and update some files so that the dropdown works correctly. +When a new GitLab version is released on the 22nd, we need to release the published documentation +for the new version. -## 1. Add the chart version +This should be done as soon as possible after the GitLab version is announced, so that: -Since the charts use a different version number than all the other GitLab -products, we need to add a -[version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html): +- The published documentation includes the three most recent minor releases of the current major + version, and the most recent minor releases of the last two major versions. For example 13.9, + 13.8, 13.7, 12.10, and 11.11. +- Documentation updates after the 22nd are for the next release. The versions drop down + should have the current milestone with `-pre` appended to it, for example `13.10-pre`. -The charts stable branch is not created automatically like the other products. -There's an [issue to track this](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1442). -It is usually created on the 21st or the 22nd. +Each documentation release: -To add a new charts version: +- Has a dedicated branch, named in the format `XX.yy`. +- Has a Docker image that contains a build of that branch. + +For example: + +- For [GitLab 13.9](https://docs.gitlab.com/13.9/index.html), the + [stable branch](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/13.9) and Docker image: + [`registry.gitlab.com/gitlab-org/gitlab-docs:13.9`](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635). +- For [GitLab 13.8](https://docs.gitlab.com/13.8/index.html), the + [stable branch](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/13.8) and Docker image: + [`registry.gitlab.com/gitlab-org/gitlab-docs:13.8`](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635). + +To set up a documentation release, follow these steps: + +1. [Add the charts version](#add-chart-version), so that the documentation is built using the + [version of the charts project that maps to](https://docs.gitlab.com/charts/installation/version_mappings.html) + the GitLab release. This step may have been completed already. +1. [Create a stable branch and Docker image](#create-stable-branch-and-docker-image-for-release) for + the new version. +1. [Create a release merge request](#create-release-merge-request) for the new version, which + updates the version dropdown menu for the current documentation and adds the release to the + Docker configuration. For example, the + [release merge request for 13.9](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1555). +1. [Update the three online versions](#update-dropdown-for-online-versions), so that they display the new release on their + version dropdown menus. For example: + - The merge request to [update the 13.9 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1556). + - The merge request to [update the 13.8 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1557). + - The merge request to [update the 13.7 version dropdown menu for the 13.9 release](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1558). +1. [Merge the release merge request and run the necessary Docker image builds](#merge-release-merge-request-and-run-docker-image-builds). + +## Add chart version + +To add a new charts version for the release: 1. Make sure you're in the root path of the `gitlab-docs` repository. 1. Open `content/_data/chart_versions.yaml` and add the new stable branch version using the - version mapping. Note that only the `major.minor` version is needed. + [version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html). Only the + `major.minor` version is needed. 1. Create a new merge request and merge it. NOTE: -It can be handy to create the future mappings since they are pretty much known. -In that case, when a new GitLab version is released, you don't have to repeat -this first step. +If you have time, add anticipated future mappings to `content/_data/chart_versions.yaml`. This saves +a step for the next GitLab release. -## 2. Create an image for a single version +## Create stable branch and Docker image for release -The single docs version must be created before the release merge request, but -this needs to happen when the stable branches for all products have been created. +To create a stable branch and Docker image for the release: 1. Make sure you're in the root path of the `gitlab-docs` repository. -1. Run the Rake task to create the single version: +1. Run the Rake task to create the single version. For example, to create the 13.9 release branch + and perform others tasks: ```shell - ./bin/rake "release:single[12.0]" + ./bin/rake "release:single[13.9]" ``` - A new `Dockerfile.12.0` should have been created and `.gitlab-ci.yml` should - have the branches variables updated into a new branch. They are automatically - committed. + A branch for the release is created, a new `Dockerfile.13.9` is created, and `.gitlab-ci.yml` + has branches variables updated into a new branch. These files are automatically committed. + +1. Push the newly created branch, but **don't create a merge request**. After you push, the + `image:docs-single` job creates a new Docker image tagged with the name of the branch you created + earlier. You can see the Docker image in the `registry` environment at + <https://gitlab.com/gitlab-org/gitlab-docs/-/environments/folders/registry>. -1. Push the newly created branch, but **don't create a merge request**. - After you push, the `image:docs-single` job creates a new Docker image - tagged with the branch name you created in the first step. In the end, the - image is uploaded in the [Container Registry](https://gitlab.com/gitlab-org/gitlab-docs/container_registry) - and it is listed under the `registry` environment folder at - `https://gitlab.com/gitlab-org/gitlab-docs/-/environments/folders/registry` (must - have developer access). +For example, see [the 13.9 release pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/260288747). -Optionally, you can test locally by building the image and running it: +Optionally, you can test locally by: -```shell -docker build -t docs:12.0 -f Dockerfile.12.0 . -docker run -it --rm -p 4000:4000 docs:12.0 -``` +1. Building the image and running it. For example, for GitLab 13.9 documentation: -Visit `http://localhost:4000/12.0/` to see if everything works correctly. + ```shell + docker build -t docs:13.9 -f Dockerfile.13.9 . + docker run -it --rm -p 4000:4000 docs:13.9 + ``` -## 3. Create the release merge request +1. Visiting <http://localhost:4000/13.9/> to see if everything works correctly. + +## Create release merge request NOTE: -To be [automated](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/750). +An [epic is open](https://gitlab.com/groups/gitlab-org/-/epics/4361) to automate this step. -Now it's time to create the monthly release merge request that adds the new -version and rotates the old one: +To create the release merge request for the release: 1. Make sure you're in the root path of the `gitlab-docs` repository. -1. Create a branch `release-X-Y`: +1. Create a branch `release-X-Y`. For example: ```shell git checkout master - git checkout -b release-12-0 + git checkout -b release-13-9 ``` -1. **Rotate the online and offline versions:** - - At any given time, there are 4 browsable online versions: one pulled from - the upstream master branches (docs for GitLab.com) and the three latest - stable versions. +1. Edit `content/_data/versions.yaml` and update the lists of versions to reflect the new release: - Edit `content/_data/versions.yaml` and rotate the versions to reflect the - new changes: + - Add the latest version to the `online:` section. + - Move the oldest version in `online:` to the `offline:` section. There should now be three + versions in `online:`. - - `online`: The 3 latest stable versions. - - `offline`: All the previous versions offered as an offline archive. +1. Update these Dockerfiles: -1. **Update the `:latest` and `:archives` Docker images:** + - `dockerfiles/Dockerfile.archives`: Add the latest version to the top of the list. + - `Dockerfile.master`: Remove the oldest version, and add the newest version to the + top of the list. - The following two Dockerfiles need to be updated: - - 1. `dockerfiles/Dockerfile.archives` - Add the latest version at the top of - the list. - 1. `Dockerfile.master` - Rotate the versions (oldest gets removed and latest - is added at the top of the list). - -1. In the end, there should be four files in total that have changed. - Commit and push to create the merge request using the "Release" template: +1. Commit and push to create the merge request. For example: ```shell git add content/ Dockerfile.master dockerfiles/Dockerfile.archives - git commit -m "Release 12.0" - git push origin release-12-0 + git commit -m "Release 13.9" + git push origin release-13-9 ``` -## 4. Update the dropdown for all online versions - -The versions dropdown is in a way "hardcoded". When the site is built, it looks -at the contents of `content/_data/versions.yaml` and based on that, the dropdown -is populated. Older branches have different content, which means the -dropdown list is one or more releases behind. Remember that the new changes of -the dropdown are included in the unmerged `release-X-Y` branch. +Do not merge the release merge request yet. -The content of `content/_data/versions.yaml` needs to change for all online -versions (stable branches `X.Y` of the `gitlab-docs` project): +## Update dropdown for online versions -1. Run the Rake task that creates all the respective merge requests needed to - update the dropdowns. Set these to automatically be merged when their - pipelines succeed: +To update`content/_data/versions.yaml` for all online versions (stable branches `X.Y` of the +`gitlab-docs` project): - NOTE: - The `release-X-Y` branch needs to be present locally, - and you need to have switched to it, otherwise the Rake task fails. +1. Run the Rake task that creates all of the necessary merge requests to update the dropdowns. For + example, for the 13.9 release: ```shell - git checkout release-X-Y + git checkout release-13-9 ./bin/rake release:dropdowns ``` -1. [Visit the merge requests page](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests?label_name%5B%5D=release) - to check that their pipelines pass, and once all are merged, proceed to the - following and final step. + These merge requests are set to automatically merge. -NOTE: -In case a pipeline fails, see [troubleshooting](#troubleshooting). +1. [Visit the merge requests page](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests?label_name%5B%5D=release) + to check that their pipelines pass. After all MRs are merged, proceed to the following and final + step. -## 5. Merge the release merge request +## Merge release merge request and run Docker image builds -The dropdown merge requests should have now been merged into their respective -version (stable `X.Y` branch), which triggers another pipeline. At this point, -you need to only babysit the pipelines and make sure they don't fail: +The merge requests for the dropdowns should now all be merged into their respective stable branches. +Each merge triggers a new pipeline for each stable branch. Wait for the stable branch pipelines to +complete, then: 1. Check the [pipelines page](https://gitlab.com/gitlab-org/gitlab-docs/pipelines) and make sure all stable branches have green pipelines. -1. After all the pipelines of the online versions succeed, merge the release merge request. +1. After all the pipelines succeed, merge the [release merge request](#create-release-merge-request). 1. Finally, run the [`Build docker images weekly` pipeline](https://gitlab.com/gitlab-org/gitlab-docs/pipeline_schedules) that builds the `:latest` and `:archives` Docker images. -Once the scheduled pipeline succeeds, the docs site is deployed with all -new versions online. - -## Troubleshooting - -Releasing a new version is a long process that involves many moving parts. - -### `test_internal_links_and_anchors` failing on dropdown merge requests - -WARNING: -We now pin versions in the `.gitlab-ci.yml` of the respective branch, -so the steps below are deprecated. - -When [updating the dropdown for the stable versions](#4-update-the-dropdown-for-all-online-versions), -there may be cases where some links might fail. The process of how the -dropdown MRs are created have a caveat, and that is that the tests run by -pulling the master branches of all products, instead of the respective stable -ones. - -In a real world scenario, the [Update 12.2 dropdown to match that of 12.4](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/604) -merge request failed because of the [`test_internal_links_and_anchors` test](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/328042431). - -This happened because there has been a rename of a product (`gitlab-monitor` to `gitlab-exporter`) -and the old name was still referenced in the 12.2 docs. If the respective stable -branches for 12.2 were used, this wouldn't have failed, but as we can see from -the [`compile_dev` job](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/328042427), -the `master` branches were pulled. - -To fix this, re-run the pipeline (`https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new`) -for the `update-12-2-for-release-12-4` branch, by including the following environment variables: - -- `BRANCH_CE` set to `12-2-stable` -- `BRANCH_EE` set to `12-2-stable-ee` -- `BRANCH_OMNIBUS` set to `12-2-stable` -- `BRANCH_RUNNER` set to `12-2-stable` -- `BRANCH_CHARTS` set to `2-2-stable` - -This should make the MR pass. +As the last step in the scheduled pipeline, the documentation site deploys with all new versions. diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md deleted file mode 100644 index ade0b89a92c..00000000000 --- a/doc/development/documentation/styleguide.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -redirect_to: 'styleguide/index.md' ---- - -This document was moved to [another location](styleguide/index.md). - -<!-- This redirect file can be deleted after <2022-02-13>. --> -<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md index 7737aa58506..4831e5bbce5 100644 --- a/doc/development/documentation/styleguide/index.md +++ b/doc/development/documentation/styleguide/index.md @@ -108,7 +108,7 @@ of GitLab more efficient. New information that would be useful toward the future usage or troubleshooting of GitLab should not be written directly in a forum or other messaging system, -but added to a documentation MR and then referenced, as described above. +but added to a documentation MR and then referenced, as described above. The more we reflexively add information to the documentation, the more the documentation helps others efficiently accomplish tasks and solve problems. @@ -601,6 +601,7 @@ Follow these guidelines for punctuation: | Rule | Example | |------------------------------------------------------------------|--------------------------------------------------------| +| Avoid semicolons. Use two sentences instead. | _That's the way that the world goes 'round. You're up one day and the next you're down._ | Always end full sentences with a period. | _For a complete overview, read through this document._ | | Always add a space after a period when beginning a new sentence. | _For a complete overview, check this doc. For other references, check out this guide._ | | Do not use double spaces. (Tested in [`SentenceSpacing.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SentenceSpacing.yml).) | --- | @@ -1606,34 +1607,32 @@ displayed for the page or feature. #### Version text in the **Version History** -If all content in a section is related, add version text after the header -for the section. The version information must be surrounded by blank lines, and -each entry should be on its own line. +If all content in a section is related, add version text after the header for +the section. The version information must: -Add the version history information as a blockquote: +- Be surrounded by blank lines. +- Start with `>`. If there are multiple bullets, each line must start with `> -`. +- The string must include these words in this order (capitalization doesn't matter): + - `introduced`, `deprecated`, `moved` + - `in` or `to` + - `GitLab` +- Whenever possible, include a link to the completed issue, merge request, or epic + that introduced the feature. An issue is preferred over a merge request, and + a merge request is preferred over an epic. ```markdown ## Feature name -> Introduced in GitLab 11.3. +> [Introduced](<link-to-issue>) in GitLab 11.3. This feature does something. -``` -Whenever possible, version text should have a link to the completed issue, merge -request, or epic that introduced the feature. An issue is preferred over a merge -request, and a merge request is preferred over an epic. For example: +## Feature name 2 -```markdown -> [Introduced](<link-to-issue>) in GitLab 11.3. -``` - -If you're adding information about new features or changes in a release, update -the blockquote to use a bulleted list: - -```markdown > - [Introduced](<link-to-issue>) in GitLab 11.3. -> - Enabled by default in GitLab 11.4. +> - [Enabled by default](<link-to-issue>) in GitLab 11.4. + +This feature does something else. ``` If a feature is moved to another tier: diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md index f3d6e0a5c71..eed544911cb 100644 --- a/doc/development/documentation/testing.md +++ b/doc/development/documentation/testing.md @@ -272,7 +272,11 @@ To configure Vale in your editor, install one of the following as appropriate: In the extension's settings: - Select the **Use CLI** checkbox. - - In the **Config** setting, enter an absolute path to [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini) in one of the cloned GitLab repositories on your computer. + - In the <!-- vale gitlab.Spelling = NO --> **Config** setting, enter an absolute + path to [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini) + in one of the cloned GitLab repositories on your computer. + <!-- vale gitlab.Spelling = YES --> + - In the **Path** setting, enter the absolute path to the Vale binary. In most cases, `vale` should work. To find the location, run `which vale` in a terminal. diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md index 3392bd1fbf6..3f14ca454fe 100644 --- a/doc/development/elasticsearch.md +++ b/doc/development/elasticsearch.md @@ -184,7 +184,7 @@ If the current version is `v12p1`, and we need to create a new version for `v12p 1. Change the namespace for files under `v12p1` folder from `Latest` to `V12p1` 1. Make changes to files under the `latest` folder as needed -## Creating a new Global Search migration +## Creating a new Advanced Search migration > This functionality was introduced by [#234046](https://gitlab.com/gitlab-org/gitlab/-/issues/234046). @@ -219,7 +219,9 @@ Any update to the Elastic index mappings should be replicated in [`Elastic::Late Migrations can be built with a retry limit and have the ability to be [failed and marked as halted](https://gitlab.com/gitlab-org/gitlab/-/blob/66e899b6637372a4faf61cfd2f254cbdd2fb9f6d/ee/lib/elastic/migration.rb#L40). Any data or index cleanup needed to support migration retries should be handled within the migration. -### Migration options supported by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb) +### Migration options supported by the `Elastic::MigrationWorker` + +[`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb) supports the following migration options: - `batched!` - Allow the migration to run in batches. If set, the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb) will re-enqueue itself with a delay which is set using the `throttle_delay` option described below. The batching @@ -230,6 +232,9 @@ enough time to finish. Additionally, the time should be less than 30 minutes sin [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb) cron worker runs. Default value is 5 minutes. +- `pause_indexing!` - Pause indexing while the migration runs. This setting will record the indexing setting before +the migration runs and set it back to that value when the migration is completed. + ```ruby # frozen_string_literal: true @@ -242,6 +247,102 @@ class BatchedMigrationName < Elastic::Migration end ``` +### Multi-version compatibility + +These Advanced Search migrations, like any other GitLab changes, need to support the case where +[multiple versions of the application are running at the same time](multi_version_compatibility.md). + +Depending on the order of deployment, it's possible that the migration +has started or finished and there's still a server running the application code from before the +migration. We need to take this into consideration until we can [ensure all Advanced Search migrations +start after the deployment has finished](https://gitlab.com/gitlab-org/gitlab/-/issues/321619). + +### Reverting a migration + +Because Elasticsearch does not support transactions, we always need to design our +migrations to accommodate a situation where the application +code is reverted after the migration has started or after it is finished. + +For this reason we generally defer destructive actions (for example, deletions after +some data is moved) to a later merge request after the migrations have +completed successfully. To be safe, for self-managed customers we should also +defer it to another release if there is risk of important data loss. + +### Best practices for Advanced Search migrations + +Follow these best practices for best results: + +- When working in batches, keep the batch size under 9,000 documents + and `throttle_delay` over 3 minutes. The bulk indexer is set to run + every 1 minute and process a batch of 10,000 documents. These limits + allow the bulk indexer time to process records before another migration + batch is attempted. +- To ensure that document counts are up to date, it is recommended to refresh + the index before checking if a migration is completed. +- Add logging statements to each migration when the migration starts, when a + completion check occurs, and when the migration is completed. These logs + are helpful when debugging issues with migrations. +- Pause indexing if you're using any Elasticsearch Reindex API operations. +- Consider adding a retry limit if there is potential for the migration to fail. + This ensures that migrations can be halted if an issue occurs. + +## Deleting Advanced Search migrations in a major version upgrade + +Since our Advanced Search migrations usually require us to support multiple +code paths for a long period of time, it's important to clean those up when we +safely can. + +We choose to use GitLab major version upgrades as a safe time to remove +backwards compatibility for indices that have not been fully migrated. We +[document this in our upgrade +documentation](../update/index.md#upgrading-to-a-new-major-version). We also +choose to remove the migration code and tests so that: + +- We don't need to maintain any code that is called from our Advanced Search + migrations. +- We don't waste CI time running tests for migrations that we don't support + anymore. + +To be extra safe, we will not delete migrations that were created in the last +minor version before the major upgrade. So, if the we are upgrading to `%14.0`, +we should not delete migrations that were only added in `%13.11`. This is an +extra safety net as we expect there are migrations that get merged that may +take multiple weeks to finish on GitLab.com. It would be bad if we upgraded +GitLab.com to `%14.0` before the migrations in `%13.11` were finished. Since +our deployments to GitLab.com are automated and we currently don't have +automated checks to prevent this, the extra precaution is warranted. +Additionally, even if we did have automated checks to prevent it, we wouldn't +actually want to hold up GitLab.com deployments on Advanced Search migrations, +as they may still have another week to go, and that's too long to block +deployments. + +### Process for removing migrations + +For every migration that was created 2 minor versions before the major version +being upgraded to, we do the following: + +1. Confirm the migration has actually completed successfully for GitLab.com. +1. Replace the content of `migrate` and `completed?` methods as follows: + + ```ruby + def migrate + log_raise "Migration has been deleted in the last major version upgrade." \ + "Migrations are supposed to be finished before upgrading major version https://docs.gitlab.com/ee/update/#upgrading-to-a-new-major-version ." \ + "In order to correct this issue you will need to reacreate your index from scratch https://docs.gitlab.com/ee/integration/elasticsearch.html#last-resort-to-recreate-an-index ." + end + + def completed? + false + end + ``` + +1. Delete any spec files to support this migration. +1. Remove any logic handling backwards compatibility for this migration. You + can find this by looking for + `Elastic::DataMigrationService.migration_has_finished?(:migration_name_in_lowercase)`. +1. Create a merge request with these changes. Noting that we should not + accidentally merge this before the major release is started. + ## Performance Monitoring ### Prometheus diff --git a/doc/development/emails.md b/doc/development/emails.md index 0b1f3c5b74c..1de1da33dc2 100644 --- a/doc/development/emails.md +++ b/doc/development/emails.md @@ -4,7 +4,7 @@ group: unassigned 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 --- -# Dealing with email in development +# Working with email in development ## Ensuring compatibility with mailer Sidekiq jobs @@ -54,7 +54,8 @@ See the [Rails guides](https://guides.rubyonrails.org/action_mailer_basics.html# incoming_email: enabled: true - # The email address including the `%{key}` placeholder that will be replaced to reference the item being replied to. + # The email address including the %{key} placeholder that will be replaced to reference the item being replied to. This %{key} should be included in its entirety within the email address and not replaced by another value. + # For example: emailadress+%key@gmail.com. # The placeholder can be omitted but if present, it must appear in the "user" part of the address (before the `@`). address: "gitlab-incoming+%{key}@gmail.com" diff --git a/doc/development/experiment_guide/experimentation.md b/doc/development/experiment_guide/experimentation.md new file mode 100644 index 00000000000..7135f8acd9b --- /dev/null +++ b/doc/development/experiment_guide/experimentation.md @@ -0,0 +1,399 @@ +--- +stage: Growth +group: Activation +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 +--- + +# Create an A/B test with `Experimentation Module` + +## Implement the experiment + +1. Add the experiment to the `Gitlab::Experimentation::EXPERIMENTS` hash in + [`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib%2Fgitlab%2Fexperimentation.rb): + + ```ruby + EXPERIMENTS = { + other_experiment: { + #... + }, + # Add your experiment here: + signup_flow: { + tracking_category: 'Growth::Activation::Experiment::SignUpFlow' # Used for providing the category when setting up tracking data + } + }.freeze + ``` + +1. Use the experiment in the code. + + Experiments can be performed on a `subject`. The provided `subject` should + respond to `to_global_id` or `to_s`. + The resulting string is bucketed and assigned to either the control or the + experimental group, so you must always provide the same `subject` + for an experiment to have the same experience. + + 1. Use this standard for the experiment in a controller: + + - Experiment run for a user: + + ```ruby + class ProjectController < ApplicationController + def show + # experiment_enabled?(:experiment_key) is also available in views and helpers + if experiment_enabled?(:signup_flow, subject: current_user) + # render the experiment + else + # render the original version + end + end + end + ``` + + - Experiment run for a namespace: + + ```ruby + if experiment_enabled?(:signup_flow, subject: namespace) + # experiment code + else + # control code + end + ``` + + When no subject is given, it falls back to a cookie that gets set and is consistent until + the cookie gets deleted. + + ```ruby + class RegistrationController < ApplicationController + def show + # falls back to a cookie + if experiment_enabled?(:signup_flow) + # render the experiment + else + # render the original version + end + end + end + ``` + + 1. Make the experiment available to the frontend in a controller. This example + checks whether the experiment is enabled and pushes the result to the frontend: + + ```ruby + before_action do + push_frontend_experiment(:signup_flow, subject: current_user) + end + ``` + + You can check the state of the feature flag in JavaScript: + + ```javascript + import { isExperimentEnabled } from '~/experimentation'; + + if ( isExperimentEnabled('signupFlow') ) { + // ... + } + ``` + +You can also run an experiment outside of the controller scope, such as in a worker: + +```ruby +class SomeWorker + def perform + # Check if the experiment is active at all (the percentage_of_time_value > 0) + return unless Gitlab::Experimentation.active?(:experiment_key) + + # Since we cannot access cookies in a worker, we need to bucket models + # based on a unique, unchanging attribute instead. + # It is therefore necessery to always provide the same subject. + if Gitlab::Experimentation.in_experiment_group?(:experiment_key, subject: user) + # execute experimental code + else + # execute control code + end + end +end +``` + +## Implement tracking events + +To determine whether the experiment is a success or not, we must implement tracking events +to acquire data for analyzing. We can send events to Snowplow via either the backend or frontend. +Read the [product intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) for more details. + +### Track backend events + +The framework provides a helper method that is available in controllers: + +```ruby +before_action do + track_experiment_event(:signup_flow, 'action', 'value', subject: current_user) +end +``` + +To test it: + +```ruby +context 'when the experiment is active and the user is in the experimental group' do + before do + stub_experiment(signup_flow: true) + stub_experiment_for_subject(signup_flow: true) + end + + it 'tracks an event', :snowplow do + subject + + expect_snowplow_event( + category: 'Growth::Activation::Experiment::SignUpFlow', + action: 'action', + value: 'value', + label: 'experimentation_subject_id', + property: 'experimental_group' + ) + end +end +``` + +### Track frontend events + +The framework provides a helper method that is available in controllers: + +```ruby +before_action do + push_frontend_experiment(:signup_flow, subject: current_user) + frontend_experimentation_tracking_data(:signup_flow, 'action', 'value', subject: current_user) +end +``` + +This pushes tracking data to `gon.experiments` and `gon.tracking_data`. + +```ruby +expect(Gon.experiments['signupFlow']).to eq(true) + +expect(Gon.tracking_data).to eq( + { + category: 'Growth::Activation::Experiment::SignUpFlow', + action: 'action', + value: 'value', + label: 'experimentation_subject_id', + property: 'experimental_group' + } +) +``` + +To track it: + +```javascript +import { isExperimentEnabled } from '~/lib/utils/experimentation'; +import Tracking from '~/tracking'; + +document.addEventListener('DOMContentLoaded', () => { + const signupFlowExperimentEnabled = isExperimentEnabled('signupFlow'); + + if (signupFlowExperimentEnabled && gon.tracking_data) { + const { category, action, ...data } = gon.tracking_data; + + Tracking.event(category, action, data); + } +} +``` + +To test it in Jest: + +```javascript +import { withGonExperiment } from 'helpers/experimentation_helper'; +import Tracking from '~/tracking'; + +describe('event tracking', () => { + describe('with tracking data', () => { + withGonExperiment('signupFlow'); + + beforeEach(() => { + jest.spyOn(Tracking, 'event').mockImplementation(() => {}); + + gon.tracking_data = { + category: 'Growth::Activation::Experiment::SignUpFlow', + action: 'action', + value: 'value', + label: 'experimentation_subject_id', + property: 'experimental_group' + }; + }); + + it('should track data', () => { + performAction() + + expect(Tracking.event).toHaveBeenCalledWith( + 'Growth::Activation::Experiment::SignUpFlow', + 'action', + { + value: 'value', + label: 'experimentation_subject_id', + property: 'experimental_group' + }, + ); + }); + }); +}); +``` + +## Record experiment user + +In addition to the anonymous tracking of events, we can also record which users +have participated in which experiments, and whether they were given the control +experience or the experimental experience. + +The `record_experiment_user` helper method is available to all controllers, and it +enables you to record these experiment participants (the current user) and which +experience they were given: + +```ruby +before_action do + record_experiment_user(:signup_flow) +end +``` + +Subsequent calls to this method for the same experiment and the same user have no +effect unless the user is then enrolled into a different experience. This happens +when we roll out the experimental experience to a greater percentage of users. + +This data is completely separate from the [events tracking data](#implement-tracking-events). +They are not linked together in any way. + +### Add context + +You can add arbitrary context data in a hash which gets stored as part of the experiment +user record. New calls to the `record_experiment_user` with newer contexts are merged +deeply into the existing context. + +This data can then be used by data analytics dashboards. + +```ruby +before_action do + record_experiment_user(:signup_flow, foo: 42, bar: { a: 22}) + # context is { "foo" => 42, "bar" => { "a" => 22 }} +end + +# Additional contexts for newer record calls are merged deeply +record_experiment_user(:signup_flow, foo: 40, bar: { b: 2 }, thor: 3) +# context becomes { "foo" => 40, "bar" => { "a" => 22, "b" => 2 }, "thor" => 3} +``` + +## Record experiment conversion event + +Along with the tracking of backend and frontend events and the +[recording of experiment participants](#record-experiment-user), we can also record +when a user performs the desired conversion event action. For example: + +- **Experimental experience:** Show an in-product nudge to test if the change causes more + people to sign up for trials. +- **Conversion event:** The user starts a trial. + +The `record_experiment_conversion_event` helper method is available to all controllers. +Use it to record the conversion event for the current user, regardless of whether +the user is in the control or experimental group: + +```ruby +before_action do + record_experiment_conversion_event(:signup_flow) +end +``` + +Note that the use of this method requires that we have first +[recorded the user](#record-experiment-user) as being part of the experiment. + +## Enable the experiment + +After all merge requests have been merged, use [ChatOps](../../ci/chatops/index.md) in the +[appropriate channel](../feature_flags/controls.md#communicate-the-change) to start the experiment for 10% of the users. +The feature flag should have the name of the experiment with the `_experiment_percentage` suffix appended. +For visibility, share any commands run against production in the `#s_growth` channel: + + ```shell + /chatops run feature set signup_flow_experiment_percentage 10 + ``` + + If you notice issues with the experiment, you can disable the experiment by removing the feature flag: + + ```shell + /chatops run feature delete signup_flow_experiment_percentage + ``` + +## Add user to experiment group manually + +To force the application to add your current user into the experiment group, +add a query string parameter to the path where the experiment runs. If you add the +query string parameter, the experiment works only for this request, and doesn't work +after following links or submitting forms. + +For example, to forcibly enable the `EXPERIMENT_KEY` experiment, add `force_experiment=EXPERIMENT_KEY` +to the URL: + +```shell +https://gitlab.com/<EXPERIMENT_ENTRY_URL>?force_experiment=<EXPERIMENT_KEY> +``` + +## Add user to experiment group with a cookie + +You can force the current user into the experiment group for `<EXPERIMENT_KEY>` +during the browser session by using your browser's developer tools: + +```javascript +document.cookie = "force_experiment=<EXPERIMENT_KEY>; path=/"; +``` + +Use a comma to list more than one experiment to be forced: + +```javascript +document.cookie = "force_experiment=<EXPERIMENT_KEY>,<ANOTHER_EXPERIMENT_KEY>; path=/"; +``` + +To clear the experiments, unset the `force_experiment` cookie: + +```javascript +document.cookie = "force_experiment=; path=/"; +``` + +## Testing and test helpers + +### RSpec + +Use the following in RSpec to mock the experiment: + +```ruby +context 'when the experiment is active' do + before do + stub_experiment(signup_flow: true) + end + + context 'when the user is in the experimental group' do + before do + stub_experiment_for_subject(signup_flow: true) + end + + it { is_expected.to do_experimental_thing } + end + + context 'when the user is in the control group' do + before do + stub_experiment_for_subject(signup_flow: false) + end + + it { is_expected.to do_control_thing } + end +end +``` + +### Jest + +Use the following in Jest to mock the experiment: + +```javascript +import { withGonExperiment } from 'helpers/experimentation_helper'; + +describe('given experiment is enabled', () => { + withGonExperiment('signupFlow'); + + it('should do the experimental thing', () => { + expect(wrapper.find('.js-some-experiment-triggered-element')).toEqual(expect.any(Element)); + }); +}); +``` diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md new file mode 100644 index 00000000000..6b15449b812 --- /dev/null +++ b/doc/development/experiment_guide/gitlab_experiment.md @@ -0,0 +1,547 @@ +--- +stage: Growth +group: Adoption +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 +--- + +# Implementing an A/B/n experiment using GLEX + +## Introduction + +`Gitlab::Experiment` (GLEX) is tightly coupled with the concepts provided by +[Feature flags in development of GitLab](../feature_flags/index.md). Here, we refer +to this layer as feature flags, and may also use the term Flipper, because we +built our development and experiment feature flags atop it. + +You're strongly encouraged to read and understand the +[Feature flags in development of GitLab](../feature_flags/index.md) portion of the +documentation before considering running experiments. Experiments add additional +concepts which may seem confusing or advanced without understanding the underpinnings +of how GitLab uses feature flags in development. One concept: GLEX supports multivariate +experiments, which are sometimes referred to as A/B/n tests. + +The [`gitlab-experiment` project](https://gitlab.com/gitlab-org/gitlab-experiment) +exists in a separate repository, so it can be shared across any GitLab property that uses +Ruby. You should feel comfortable reading the documentation on that project as well +if you want to dig into more advanced topics. + +## Glossary of terms + +To ensure a shared language, you should understand these fundamental terms we use +when communicating about experiments: + +- `experiment`: Any deviation of code paths we want to run at some times, but not others. +- `context`: A consistent experience we provide in an experiment. +- `control`: The default, or "original" code path. +- `candidate`: Defines an experiment with only one code path. +- `variant(s)`: Defines an experiment with multiple code paths. + +### How it works + +Use this decision tree diagram to understand how GLEX works. When an experiment runs, +the following logic is executed to determine what variant should be provided, +given how the experiment has been defined and using the provided context: + +```mermaid +graph TD + GP[General Pool/Population] --> Running? + Running? -->|Yes| Cached?[Cached? / Pre-segmented?] + Running? -->|No| Excluded[Control / No Tracking] + Cached? -->|No| Excluded? + Cached? -->|Yes| Cached[Cached Value] + Excluded? -->|Yes / Cached| Excluded + Excluded? -->|No| Segmented? + Segmented? -->|Yes / Cached| VariantA + Segmented? -->|No| Included?[Experiment Group?] + Included? -->|Yes| Rollout + Included? -->|No| Control + Rollout -->|Cached| VariantA + Rollout -->|Cached| VariantB + Rollout -->|Cached| VariantC + +classDef included fill:#380d75,color:#ffffff,stroke:none +classDef excluded fill:#fca121,stroke:none +classDef cached fill:#2e2e2e,color:#ffffff,stroke:none +classDef default fill:#fff,stroke:#6e49cb + +class VariantA,VariantB,VariantC included +class Control,Excluded excluded +class Cached cached +``` + +## Implement an experiment + +Start by generating a feature flag using the `bin/feature-flag` command as you +normally would for a development feature flag, making sure to use `experiment` for +the type. For the sake of documentation let's name our feature flag (and experiment) +"pill_color". + +```shell +bin/feature-flag pill_color -t experiment +``` + +After you generate the desired feature flag, you can immediately implement an +experiment in code. An experiment implementation can be as simple as: + +```ruby +experiment(:pill_color, actor: current_user) do |e| + e.use { 'control' } + e.try(:red) { 'red' } + e.try(:blue) { 'blue' } +end +``` + +When this code executes, the experiment is run, a variant is assigned, and (if within a +controller or view) a `window.gon.experiment.pillColor` object will be available in the +client layer, with details like: + +- The assigned variant. +- The context key for client tracking events. + +In addition, when an experiment runs, an event is tracked for +the experiment `:assignment`. We cover more about events, tracking, and +the client layer later. + +In local development, you can make the experiment active by using the feature flag +interface. You can also target specific cases by providing the relevant experiment +to the call to enable the feature flag: + +```ruby +# Enable for everyone +Feature.enable(:pill_color) + +# Get the `experiment` method -- already available in controllers, views, and mailers. +include Gitlab::Experiment::Dsl +# Enable for only the first user +Feature.enable(:pill_color, experiment(:pill_color, actor: User.first)) +``` + +To roll out your experiment feature flag on an environment, run +the following command using ChatOps (which is covered in more depth in the +[Feature flags in development of GitLab](../feature_flags/index.md) documentation). +This command creates a scenario where half of everyone who encounters +the experiment would be assigned the _control_, 25% would be assigned the _red_ +variant, and 25% would be assigned the _blue_ variant: + +```slack +/chatops run feature set pill_color 50 --actors +``` + +For an even distribution in this example, change the command to set it to 66% instead +of 50. + +NOTE: +To immediately stop running an experiment, use the +`/chatops run feature set pill_color false` command. + +WARNING: +We strongly recommend using the `--actors` flag when using the ChatOps commands, +as anything else may give odd behaviors due to how the caching of variant assignment is +handled. + +We can also implement this experiment in a HAML file with HTML wrappings: + +```haml +#cta-interface + - experiment(:pill_color, actor: current_user) do |e| + - e.use do + .pill-button control + - e.try(:red) do + .pill-button.red red + - e.try(:blue) do + .pill-button.blue blue +``` + +### The importance of context + +In our previous example experiment, our context (this is an important term) is a hash +that's set to `{ actor: current_user }`. Context must be unique based on how you +want to run your experiment, and should be understood at a lower level. + +It's expected, and recommended, that you use some of these +contexts to simplify reporting: + +- `{ actor: current_user }`: Assigns a variant and is "sticky" to each user + (or "client" if `current_user` is nil) who enters the experiment. +- `{ project: project }`: Assigns a variant and is "sticky" to the project currently + being viewed. If running your experiment is more useful when viewing a project, + rather than when a specific user is viewing any project, consider this approach. +- `{ group: group }`: Similar to the project example, but applies to a wider + scope of projects and users. +- `{ actor: current_user, project: project }`: Assigns a variant and is "sticky" + to the user who is viewing the given project. This creates a different variant + assignment possibility for every project that `current_user` views. Understand this + can create a large cache size if an experiment like this in a highly trafficked part + of the application. +- `{ wday: Time.current.wday }`: Assigns a variant based on the current day of the + week. In this example, it would consistently assign one variant on Friday, and a + potentially different variant on Saturday. + +Context is critical to how you define and report on your experiment. It's usually +the most important aspect of how you choose to implement your experiment, so consider +it carefully, and discuss it with the wider team if needed. Also, take into account +that the context you choose affects our cache size. + +After the above examples, we can state the general case: *given a specific +and consistent context, we can provide a consistent experience and track events for +that experience.* To dive a bit deeper into the implementation details: a context key +is generated from the context that's provided. Use this context key to: + +- Determine the assigned variant. +- Identify events tracked against that context key. + +We can think about this as the experience that we've rendered, which is both dictated +and tracked by the context key. The context key is used to track the interaction and +results of the experience we've rendered to that context key. These concepts are +somewhat abstract and hard to understand initially, but this approach enables us to +communicate about experiments as something that's wider than just user behavior. + +NOTE: +Using `actor:` utilizes cookies if the `current_user` is nil. If you don't need +cookies though - meaning that the exposed functionality would only be visible to +signed in users - `{ user: current_user }` would be just as effective. + +WARNING: +The caching of variant assignment is done by using this context, and so consider +your impact on the cache size when defining your experiment. If you use +`{ time: Time.current }` you would be inflating the cache size every time the +experiment is run. Not only that, your experiment would not be "sticky" and events +wouldn't be resolvable. + +### Advanced experimentation + +GLEX allows for two general implementation styles: + +1. The simple experiment style described previously. +1. A more advanced style where an experiment class can be provided. + +The advanced style is handled by naming convention, and works similar to what you +would expect in Rails. + +To generate a custom experiment class that can override the defaults in +`ApplicationExperiment` (our base GLEX implementation), use the rails generator: + +```shell +rails generate gitlab:experiment pill_color control red blue +``` + +This generates an experiment class in `app/experiments/pill_color_experiment.rb` +with the variants (or _behaviors_) we've provided to the generator. Here's an example +of how that class would look after migrating the previous example into it: + +```ruby +class PillColorExperiment < ApplicationExperiment + def control_behavior + 'control' + end + + def red_behavior + 'red' + end + + def blue_behavior + 'blue' + end +end +``` + +We can now simplify where we run our experiment to the following call, instead of +providing the block we were initially providing, by explicitly calling `run`: + +```ruby +experiment(:pill_color, actor: current_user).run +``` + +The _behavior_ methods we defined in our experiment class represent the default +implementation. You can still use the block syntax to override these _behavior_ +methods however, so the following would also be valid: + +```ruby +experiment(:pill_color, actor: current_user) do |e| + e.use { '<strong>control</strong>' } +end +``` + +NOTE: +When passing a block to the `experiment` method, it is implicitly invoked as +if `run` has been called. + +#### Segmentation rules + +You can use runtime segmentation rules to, for instance, segment contexts into a specific +variant. The `segment` method is a callback (like `before_action`) and so allows providing +a block or method name. + +In this example, any user named `'Richard'` would always be assigned the _red_ +variant, and any account older than 2 weeks old would be assigned the _blue_ variant: + +```ruby +class PillColorExperiment < ApplicationExperiment + segment(variant: :red) { context.actor.first_name == 'Richard' } + segment :old_account?, variant: :blue + + # ...behaviors + + private + + def old_account? + context.actor.created_at < 2.weeks.ago + end +end +``` + +When an experiment runs, the segmentation rules are executed in the order they're +defined. The first segmentation rule to produce a truthy result assigns the variant. + +In our example, any user named `'Richard'`, regardless of account age, will always +be assigned the _red_ variant. If you want the opposite logic, flip the order. + +NOTE: +Keep in mind when defining segmentation rules: after a truthy result, the remaining +segmentation rules are skipped to achieve optimal performance. + +#### Exclusion rules + +Exclusion rules are similar to segmentation rules, but are intended to determine +if a context should even be considered as something we should include in the experiment +and track events toward. Exclusion means we don't care about the events in relation +to the given context. + +These examples exclude all users named `'Richard'`, *and* any account +older than 2 weeks old. Not only are they given the control behavior - which could +be nothing - but no events are tracked in these cases as well. + +```ruby +class PillColorExperiment < ApplicationExperiment + exclude :old_account?, ->{ context.actor.first_name == 'Richard' } + + # ...behaviors + + private + + def old_account? + context.actor.created_at < 2.weeks.ago + end +end +``` + +We can also do exclusion when we run the experiment. For instance, +if we wanted to prevent the inclusion of non-administrators in an experiment, consider +the following experiment. This type of logic enables us to do complex experiments +while preventing us from passing things into our experiments, because +we want to minimize passing things into our experiments: + +```ruby +experiment(:pill_color, actor: current_user) do |e| + e.exclude! unless can?(current_user, :admin_project, project) +end +``` + +You may also need to check exclusion in custom tracking logic by calling `should_track?`: + +```ruby +class PillColorExperiment < ApplicationExperiment + # ...behaviors + + def expensive_tracking_logic + return unless should_track? + + track(:my_event, value: expensive_method_call) + end +end +``` + +Exclusion rules aren't the best way to determine if an experiment is active. Override +the `enabled?` method for a high-level way of determining if an experiment should +run and track. Make the `enabled?` check as efficient as possible because it's the +first early opt-out path an experiment can implement. + +### Tracking events + +One of the most important aspects of experiments is gathering data and reporting on +it. GLEX provides an interface that allows tracking events across an experiment. +You can implement it consistently if you provide the same context between +calls to your experiment. If you do not yet understand context, you should read +about contexts now. + +We can assume we run the experiment in one or a few places, but +track events potentially in many places. The tracking call remains the same, with +the arguments you would normally use when +[tracking events using snowplow](../snowplow.md). The easiest example +of tracking an event in Ruby would be: + +```ruby +experiment(:pill_color, actor: current_user).track(:created) +``` + +When you run an experiment with any of these examples, an `:assigned` event +is tracked automatically by default. All events that are tracked from an +experiment have a special +[experiment context](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0) +added to the event. This can be used - typically by the data team - to create a connection +between the events on a given experiment. + +If our current user hasn't encountered the experiment yet (meaning where the experiment +is run), and we track an event for them, they are assigned a variant and see +that variant if they ever encountered the experiment later, when an `:assignment` +event would be tracked at that time for them. + +NOTE: +GitLab tries to be sensitive and respectful of our customers regarding tracking, +so GLEX allows us to implement an experiment without ever tracking identifying +IDs. It's not always possible, though, based on experiment reporting requirements. +You may be asked from time to time to track a specific record ID in experiments. +The approach is largely up to the PM and engineer creating the implementation. +No recommendations are provided here at this time. + +## Test with RSpec + +This gem provides some RSpec helpers and custom matchers. These are in flux as of GitLab 13.10. + +First, require the RSpec support file to mix in some of the basics: + +```ruby +require 'gitlab/experiment/rspec' +``` + +You still need to include matchers and other aspects, which happens +automatically for files in `spec/experiments`, but for other files and specs +you want to include it in, you can specify the `:experiment` type: + +```ruby +it "tests", :experiment do +end +``` + +### Stub helpers + +You can stub experiments using `stub_experiments`. Pass it a hash using experiment +names as the keys, and the variants you want each to resolve to, as the values: + +```ruby +# Ensures the experiments named `:example` & `:example2` are both +# "enabled" and that each will resolve to the given variant +# (`:my_variant` & `:control` respectively). +stub_experiments(example: :my_variant, example2: :control) + +experiment(:example) do |e| + e.enabled? # => true + e.variant.name # => 'my_variant' +end + +experiment(:example2) do |e| + e.enabled? # => true + e.variant.name # => 'control' +end +``` + +### Exclusion and segmentation matchers + +You can also test the exclusion and segmentation matchers. + +```ruby +class ExampleExperiment < ApplicationExperiment + exclude { context.actor.first_name == 'Richard' } + segment(variant: :candidate) { context.actor.username == 'jejacks0n' } +end + +excluded = double(username: 'rdiggitty', first_name: 'Richard') +segmented = double(username: 'jejacks0n', first_name: 'Jeremy') + +# exclude matcher +expect(experiment(:example)).to exclude(actor: excluded) +expect(experiment(:example)).not_to exclude(actor: segmented) + +# segment matcher +expect(experiment(:example)).to segment(actor: segmented).into(:candidate) +expect(experiment(:example)).not_to segment(actor: excluded) +``` + +### Tracking matcher + +Tracking events is a major aspect of experimentation. We try +to provide a flexible way to ensure your tracking calls are covered. + +You can do this on the instance level or at an "any instance" level: + +```ruby +subject = experiment(:example) + +expect(subject).to track(:my_event) + +subject.track(:my_event) +``` + +You can use the `on_any_instance` chain method to specify that it could happen on +any instance of the experiment. This helps you if you're calling +`experiment(:example).track` downstream: + +```ruby +expect(experiment(:example)).to track(:my_event).on_any_instance + +experiment(:example).track(:my_event) +``` + +A full example of the methods you can chain onto the `track` matcher: + +```ruby +expect(experiment(:example)).to track(:my_event, value: 1, property: '_property_') + .on_any_instance + .with_context(foo: :bar) + .for(:variant_name) + +experiment(:example, :variant_name, foo: :bar).track(:my_event, value: 1, property: '_property_') +``` + +## Experiments in the client layer + +This is in flux as of GitLab 13.10, and can't be documented just yet. + +Any experiment that's been run in the request lifecycle surfaces in `window.gon.experiment`, +and matches [this schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0) +so you can use it when resolving some concepts around experimentation in the client layer. + +## Notes on feature flags + +NOTE: +We use the terms "enabled" and "disabled" here, even though it's against our +[documentation style guide recommendations](../documentation/styleguide/index.md#avoid-ableist-language) +because these are the terms that the feature flag documentation uses. + +You may already be familiar with the concept of feature flags in GitLab, but using +feature flags in experiments is a bit different. While in general terms, a feature flag +is viewed as being either `on` or `off`, this isn't accurate for experiments. + +Generally, `off` means that when we ask if a feature flag is enabled, it will always +return `false`, and `on` means that it will always return `true`. An interim state, +considered `conditional`, also exists. GLEX takes advantage of this trinary state of +feature flags. To understand this `conditional` aspect: consider that either of these +settings puts a feature flag into this state: + +- Setting a `percentage_of_actors` of any percent greater than 0%. +- Enabling it for a single user or group. + +Conditional means that it returns `true` in some situations, but not all situations. + +When a feature flag is disabled (meaning the state is `off`), the experiment is +considered _inactive_. You can visualize this in the [decision tree diagram](#how-it-works) +as reaching the first [Running?] node, and traversing the negative path. + +When a feature flag is rolled out to a `percentage_of_actors` or similar (meaning the +state is `conditional`) the experiment is considered to be _running_ +where sometimes the control is assigned, and sometimes the candidate is assigned. +We don't refer to this as being enabled, because that's a confusing and overloaded +term here. In the experiment terms, our experiment is _running_, and the feature flag is +`conditional`. + +When a feature flag is enabled (meaning the state is `on`), the candidate will always be +assigned. + +We should try to be consistent with our terms, and so for experiments, we have an +_inactive_ experiment until we set the feature flag to `conditional`. After which, +our experiment is then considered _running_. If you choose to "enable" your feature flag, +you should consider the experiment to be _resolved_, because everyone is assigned +the candidate unless they've opted out of experimentation. + +As of GitLab 13.10, work is being done to improve this process and how we communicate +about it. diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md index 21c61324dc1..15430831f4a 100644 --- a/doc/development/experiment_guide/index.md +++ b/doc/development/experiment_guide/index.md @@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w Experiments can be conducted by any GitLab team, most often the teams from the [Growth Sub-department](https://about.gitlab.com/handbook/engineering/development/growth/). Experiments are not tied to releases because they primarily target GitLab.com. -Experiments are run as an A/B test and are behind a feature flag to turn the test on or off. Based on the data the experiment generates, the team decides if the experiment had a positive impact and should be made the new default or rolled back. +Experiments are run as an A/B/n test, and are behind a feature flag to turn the test on or off. Based on the data the experiment generates, the team decides if the experiment had a positive impact and should be made the new default, or rolled back. ## Experiment tracking issue @@ -36,386 +36,27 @@ and link to the issue that resolves the experiment. If the experiment is successful and becomes part of the product, any follow up issues should be addressed. -## Experiments using `gitlab-experiment` +## Implementing an experiment -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300383) in GitLab 13.7. -> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. -> - It's enabled on GitLab.com. -> - It is not yet intended for use in GitLab self-managed instances. +There are currently two options when implementing an experiment. -[GitLab Experiment](https://gitlab.com/gitlab-org/gitlab-experiment/) is a gem included -in GitLab that can be used for running experiments. +One is built into GitLab directly and has been around for a while (this is called +`Exerimentation Module`), and the other is provided by +[`gitlab-experiment`](https://gitlab.com/gitlab-org/gitlab-experiment) and is referred +to as `Gitlab::Experiment` -- GLEX for short. -## How to create an A/B test using `experimentation.rb` +Both approaches use [experiment](../feature_flags/index.md#experiment-type) +feature flags, and there is currently no strong suggestion to use one over the other. -### Implement the experiment +| Feature | `Experimentation Module` | GLEX | +| -------------------- |------------------------- | ---- | +| Record user grouping | Yes | No | +| Uses feature flags | Yes | Yes | +| Multivariate (A/B/n) | No | Yes | -1. Add the experiment to the `Gitlab::Experimentation::EXPERIMENTS` hash in [`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib%2Fgitlab%2Fexperimentation.rb): +- [Implementing an A/B experiment using `Experimentation Module`](experimentation.md) +- [Implementing an A/B/n experiment using GLEX](gitlab_experiment.md) - ```ruby - EXPERIMENTS = { - other_experiment: { - #... - }, - # Add your experiment here: - signup_flow: { - tracking_category: 'Growth::Activation::Experiment::SignUpFlow' # Used for providing the category when setting up tracking data - } - }.freeze - ``` - -1. Use the experiment in the code. - - Experiments can be performed on a `subject`. The `subject` that gets provided needs to respond to `to_global_id` or `to_s`. - The resulting string is bucketed and assigned to either the control or the experimental group. It's therefore necessary to always provide the same `subject` for an experiment to have the same experience. - - - Use this standard for the experiment in a controller: - - Experiment run for a user: - - ```ruby - class ProjectController < ApplicationController - def show - # experiment_enabled?(:experiment_key) is also available in views and helpers - if experiment_enabled?(:signup_flow, subject: current_user) - # render the experiment - else - # render the original version - end - end - end - ``` - - or experiment run for a namespace: - - ```ruby - if experiment_enabled?(:signup_flow, subject: namespace) - # experiment code - else - # control code - end - ``` - - When no subject is given, it falls back to a cookie that gets set and is consistent until - the cookie gets deleted. - - ```ruby - class RegistrationController < ApplicationController - def show - # falls back to a cookie - if experiment_enabled?(:signup_flow) - # render the experiment - else - # render the original version - end - end - end - ``` - - - Make the experiment available to the frontend in a controller: - - ```ruby - before_action do - push_frontend_experiment(:signup_flow, subject: current_user) - end - ``` - - The above checks whether the experiment is enabled and pushes the result to the frontend. - - You can check the state of the feature flag in JavaScript: - - ```javascript - import { isExperimentEnabled } from '~/experimentation'; - - if ( isExperimentEnabled('signupFlow') ) { - // ... - } - ``` - - - It is also possible to run an experiment outside of the controller scope, for example in a worker: - - ```ruby - class SomeWorker - def perform - # Check if the experiment is active at all (the percentage_of_time_value > 0) - return unless Gitlab::Experimentation.active?(:experiment_key) - - # Since we cannot access cookies in a worker, we need to bucket models based on a unique, unchanging attribute instead. - # It is therefore necessery to always provide the same subject. - if Gitlab::Experimentation.in_experiment_group?(:experiment_key, subject: user) - # execute experimental code - else - # execute control code - end - end - end - ``` - -### Implement the tracking events - -To determine whether the experiment is a success or not, we must implement tracking events -to acquire data for analyzing. We can send events to Snowplow via either the backend or frontend. -Read the [product intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) for more details. - -#### Track backend events - -The framework provides the following helper method that is available in controllers: - -```ruby -before_action do - track_experiment_event(:signup_flow, 'action', 'value', subject: current_user) -end -``` - -Which can be tested as follows: - -```ruby -context 'when the experiment is active and the user is in the experimental group' do - before do - stub_experiment(signup_flow: true) - stub_experiment_for_subject(signup_flow: true) - end - - it 'tracks an event', :snowplow do - subject - - expect_snowplow_event( - category: 'Growth::Activation::Experiment::SignUpFlow', - action: 'action', - value: 'value', - label: 'experimentation_subject_id', - property: 'experimental_group' - ) - end -end -``` - -#### Track frontend events - -The framework provides the following helper method that is available in controllers: - -```ruby -before_action do - push_frontend_experiment(:signup_flow, subject: current_user) - frontend_experimentation_tracking_data(:signup_flow, 'action', 'value', subject: current_user) -end -``` - -This pushes tracking data to `gon.experiments` and `gon.tracking_data`. - -```ruby -expect(Gon.experiments['signupFlow']).to eq(true) - -expect(Gon.tracking_data).to eq( - { - category: 'Growth::Activation::Experiment::SignUpFlow', - action: 'action', - value: 'value', - label: 'experimentation_subject_id', - property: 'experimental_group' - } -) -``` - -Which can then be used for tracking as follows: - -```javascript -import { isExperimentEnabled } from '~/lib/utils/experimentation'; -import Tracking from '~/tracking'; - -document.addEventListener('DOMContentLoaded', () => { - const signupFlowExperimentEnabled = isExperimentEnabled('signupFlow'); - - if (signupFlowExperimentEnabled && gon.tracking_data) { - const { category, action, ...data } = gon.tracking_data; - - Tracking.event(category, action, data); - } -} -``` - -Which can be tested in Jest as follows: - -```javascript -import { withGonExperiment } from 'helpers/experimentation_helper'; -import Tracking from '~/tracking'; - -describe('event tracking', () => { - describe('with tracking data', () => { - withGonExperiment('signupFlow'); - - beforeEach(() => { - jest.spyOn(Tracking, 'event').mockImplementation(() => {}); - - gon.tracking_data = { - category: 'Growth::Activation::Experiment::SignUpFlow', - action: 'action', - value: 'value', - label: 'experimentation_subject_id', - property: 'experimental_group' - }; - }); - - it('should track data', () => { - performAction() - - expect(Tracking.event).toHaveBeenCalledWith( - 'Growth::Activation::Experiment::SignUpFlow', - 'action', - { - value: 'value', - label: 'experimentation_subject_id', - property: 'experimental_group' - }, - ); - }); - }); -}); -``` - -### Record experiment user - -In addition to the anonymous tracking of events, we can also record which users have participated in which experiments and whether they were given the control experience or the experimental experience. - -The `record_experiment_user` helper method is available to all controllers, and it enables you to record these experiment participants (the current user) and which experience they were given: - -```ruby -before_action do - record_experiment_user(:signup_flow) -end -``` - -Subsequent calls to this method for the same experiment and the same user have no effect unless the user has gets enrolled into a different experience. This happens when we roll out the experimental experience to a greater percentage of users. - -Note that this data is completely separate from the [events tracking data](#implement-the-tracking-events). They are not linked together in any way. - -#### Add context - -You can add arbitrary context data in a hash which gets stored as part of the experiment user record. New calls to the `record_experiment_user` with newer contexts get merged deeply into the existing context. - -This data can then be used by data analytics dashboards. - -```ruby -before_action do - record_experiment_user(:signup_flow, foo: 42, bar: { a: 22}) - # context is { "foo" => 42, "bar" => { "a" => 22 }} -end - -# Additional contexts for newer record calls are merged deeply -record_experiment_user(:signup_flow, foo: 40, bar: { b: 2 }, thor: 3) -# context becomes { "foo" => 40, "bar" => { "a" => 22, "b" => 2 }, "thor" => 3} -``` - -### Record experiment conversion event - -Along with the tracking of backend and frontend events and the [recording of experiment participants](#record-experiment-user), we can also record when a user performs the desired conversion event action. For example: - -- **Experimental experience:** Show an in-product nudge to see if it causes more people to sign up for trials. -- **Conversion event:** The user starts a trial. - -The `record_experiment_conversion_event` helper method is available to all controllers. It enables us to record the conversion event for the current user, regardless of whether they are in the control or experimental group: - -```ruby -before_action do - record_experiment_conversion_event(:signup_flow) -end -``` - -Note that the use of this method requires that we have first [recorded the user as being part of the experiment](#record-experiment-user). - -### Enable the experiment - -After all merge requests have been merged, use [`chatops`](../../ci/chatops/index.md) in the -[appropriate channel](../feature_flags/controls.md#communicate-the-change) to start the experiment for 10% of the users. -The feature flag should have the name of the experiment with the `_experiment_percentage` suffix appended. -For visibility, please also share any commands run against production in the `#s_growth` channel: - - ```shell - /chatops run feature set signup_flow_experiment_percentage 10 - ``` - - If you notice issues with the experiment, you can disable the experiment by removing the feature flag: - - ```shell - /chatops run feature delete signup_flow_experiment_percentage - ``` - -### Manually force the current user to be in the experiment group - -You may force the application to put your current user in the experiment group. To do so -add a query string parameter to the path where the experiment runs. If you do so, -the experiment will work only for this request and won't work after following links or submitting forms. - -For example, to forcibly enable the `EXPERIMENT_KEY` experiment, add `force_experiment=EXPERIMENT_KEY` -to the URL: - -```shell -https://gitlab.com/<EXPERIMENT_ENTRY_URL>?force_experiment=<EXPERIMENT_KEY> -``` - -### A cookie-based approach to force an experiment - -It's possible to force the current user to be in the experiment group for `<EXPERIMENT_KEY>` -during the browser session by using your browser's developer tools: - -```javascript -document.cookie = "force_experiment=<EXPERIMENT_KEY>; path=/"; -``` - -Use a comma to list more than one experiment to be forced: - -```javascript -document.cookie = "force_experiment=<EXPERIMENT_KEY>,<ANOTHER_EXPERIMENT_KEY>; path=/"; -``` - -To clear the experiments, unset the `force_experiment` cookie: - -```javascript -document.cookie = "force_experiment=; path=/"; -``` - -### Testing and test helpers - -#### RSpec - -Use the following in RSpec to mock the experiment: - -```ruby -context 'when the experiment is active' do - before do - stub_experiment(signup_flow: true) - end - - context 'when the user is in the experimental group' do - before do - stub_experiment_for_subject(signup_flow: true) - end - - it { is_expected.to do_experimental_thing } - end - - context 'when the user is in the control group' do - before do - stub_experiment_for_subject(signup_flow: false) - end - - it { is_expected.to do_control_thing } - end -end -``` - -#### Jest - -Use the following in Jest to mock the experiment: - -```javascript -import { withGonExperiment } from 'helpers/experimentation_helper'; - -describe('given experiment is enabled', () => { - withGonExperiment('signupFlow'); - - it('should do the experimental thing', () => { - expect(wrapper.find('.js-some-experiment-triggered-element')).toEqual(expect.any(Element)); - }); -}); -``` +Historical Context: `Experimentation Module` was built iteratively with the needs that +appeared while implementing Growth sub-department experiments, while GLEX was built +with the learnings of the team and an easier to use API. diff --git a/doc/development/export_csv.md b/doc/development/export_csv.md index 0bf12149779..c301b6b9d66 100644 --- a/doc/development/export_csv.md +++ b/doc/development/export_csv.md @@ -14,7 +14,7 @@ This document lists the different implementations of CSV export in GitLab codeba | Downloading | - Query and write data in batches to a temporary file.<br>- Loads the file into memory.<br>- Sends the file to the client. | - Report available immediately. | - Large amount of data might cause request timeout.<br>- Memory intensive.<br>- Request expires when user navigates to a different page. | [Export Chain of Custody Report](../user/compliance/compliance_dashboard/#chain-of-custody-report) | | As email attachment | - Asynchronously process the query with background job.<br>- Email uses the export as an attachment. | - Asynchronous processing. | - Requires users use a different app (email) to download the CSV.<br>- Email providers may limit attachment size. | - [Export Issues](../user/project/issues/csv_export.md)<br>- [Export Merge Requests](../user/project/merge_requests/csv_export.md) | | As downloadable link in email (*) | - Asynchronously process the query with background job.<br>- Email uses an export link. | - Asynchronous processing.<br>- Bypasses email provider attachment size limit. | - Requires users use a different app (email).<br>- Requires additional storage and cleanup. | [Export User Permissions](https://gitlab.com/gitlab-org/gitlab/-/issues/1772) | -| Polling (non-persistent state) | - Asynchronously processes the query with the background job.<br>- Frontend(FE) polls every few seconds to check if CSV file is ready. | - Asynchronous processing.<br>- Automatically downloads to local machine on completion.<br>- In-app solution. | - Non-persistable request - request expires when user navigates to a different page.<br>- API is processed for each polling request. | [Export Vulnerabilities](../user/application_security/vulnerability_report/#export-vulnerabilities) | +| Polling (non-persistent state) | - Asynchronously processes the query with the background job.<br>- Frontend(FE) polls every few seconds to check if CSV file is ready. | - Asynchronous processing.<br>- Automatically downloads to local machine on completion.<br>- In-app solution. | - Non-persistable request - request expires when user navigates to a different page.<br>- API is processed for each polling request. | [Export Vulnerabilities](../user/application_security/vulnerability_report/#export-vulnerability-details) | | Polling (persistent state) (*) | - Asynchronously processes the query with background job.<br>- Backend (BE) maintains the export state<br>- FE polls every few seconds to check status.<br>- FE shows 'Download link' when export is ready.<br>- User can download or regenerate a new report. | - Asynchronous processing.<br>- No database calls made during the polling requests (HTTP 304 status is returned until export status changes).<br>- Does not require user to stay on page until export is complete.<br>- In-app solution.<br>- Can be expanded into a generic CSV feature (such as dashboard / CSV API). | - Requires to maintain export states in DB.<br>- Does not automatically download the CSV export to local machine, requires users to click 'Download' button. | [Export Merge Commits Report](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43055) | NOTE: diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md index 5ad1a701fac..5f22c13ca06 100644 --- a/doc/development/fe_guide/accessibility.md +++ b/doc/development/fe_guide/accessibility.md @@ -4,14 +4,195 @@ group: unassigned 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 --- -# Accessibility & Readability +# Accessibility + +Accessibility is important for users who use screen readers or rely on keyboard-only functionality +to ensure they have an equivalent experience to sighted mouse users. + +This page contains guidelines we should follow. + +## Quick summary + +Since [no ARIA is better than bad ARIA](https://www.w3.org/TR/wai-aria-practices/#no_aria_better_bad_aria), +review the following recommendations before using `aria-*`, `role`, and `tabindex`. +Use semantic HTML, which typically has accessibility semantics baked in, but always be sure to test with +[relevant combinations of screen readers and browsers](https://www.accessibility-developer-guide.com/knowledge/screen-readers/relevant-combinations/). + +In [WebAIM's accessibility analysis of the top million home pages](https://webaim.org/projects/million/#aria), +they found that "ARIA correlated to higher detectable errors". +It is likely that *misuse* of ARIA is a big cause of increased errors, +so when in doubt don't use `aria-*`, `role`, and `tabindex`, and stick with semantic HTML. + +## Provide accessible names to screen readers + +To provide markup with accessible names, ensure every: + +- `input` has an associated `label`. +- `button` and `a` have child text, or `aria-label` when text isn’t present. + For example, an icon button with no visible text. +- `img` has an `alt` attribute. +- `fieldset` has `legend` as its first child. +- `figure` has `figcaption` as its first child. +- `table` has `caption` as its first child. + +If the `label`, child text, or child element is not visually desired, +use `.gl-sr-only` to hide the element from everything but screen readers. + +Ensure the accessible name is descriptive enough to be understood in isolation. + +```html +// bad +<button>Submit</button> +<a href="url">page</a> + +// good +<button>Submit review</button> +<a href="url">GitLab's accessibility page</a> +``` + +## Role + +In general, avoid using `role`. +Use semantic HTML elements that implicitly have a `role` instead. + +| Bad | Good | +| --- | --- | +| `<div role="button">` | `<button>` | +| `<div role="img">` | `<img>` | +| `<div role="link">` | `<a>` | +| `<div role="header">` | `<h1>` to `<h6>` | +| `<div role="textbox">` | `<input>` or `<textarea>` | +| `<div role="article">` | `<article>` | +| `<div role="list">` | `<ol>` or `<ul>` | +| `<div role="listitem">` | `<li>` | +| `<div role="table">` | `<table>` | +| `<div role="rowgroup">` | `<thead>`, `<tbody>`, or `<tfoot>` | +| `<div role="row">` | `<tr>` | +| `<div role="columnheader">` | `<th>` | +| `<div role="cell">` | `<td>` | + +## Support keyboard-only use + +Keyboard users rely on focus outlines to understand where they are on the page. Therefore, if an +element is interactive you must ensure: + +- It can receive keyboard focus. +- It has a visible focus state. + +Use semantic HTML, such as `a` and `button`, which provides these behaviours by default. + +See the [Pajamas Keyboard-only page](https://design.gitlab.com/accessibility-audits/2-keyboard-only/) for more detail. + +## Tabindex + +Prefer **no** `tabindex` to using `tabindex`, since: + +- Using semantic HTML such as `button` implicitly provides `tabindex="0"` +- Tabbing order should match the visual reading order and positive `tabindex`s interfere with this + +### Avoid using `tabindex="0"` to make an element interactive + +Use interactive elements instead of `div`s and `span`s. +For example: + +- If the element should be clickable, use a `button` +- If the element should be text editable, use an `input` or `textarea` + +Once the markup is semantically complete, use CSS to update it to its desired visual state. + +```html +// bad +<div role="button" tabindex="0" @click="expand">Expand</div> + +// good +<button @click="expand">Expand</button> +``` + +### Do not use `tabindex="0"` on interactive elements + +Interactive elements are already tab accessible so adding `tabindex` is redundant. + +```html +// bad +<a href="help" tabindex="0">Help</a> +<button tabindex="0">Submit</button> + +// good +<a href="help">Help</a> +<button>Submit</button> +``` + +### Do not use `tabindex="0"` on elements for screen readers to read + +Screen readers can read text that is not tab accessible. +The use of `tabindex="0"` is unnecessary and can cause problems, +as screen reader users then expect to be able to interact with it. + +```html +// bad +<span tabindex="0" :aria-label="message">{{ message }}</span> + +// good +<p>{{ message }}</p> +``` + +### Do not use a positive `tabindex` + +[Always avoid using `tabindex="1"`](https://webaim.org/techniques/keyboard/tabindex#overview) +or greater. + +## Hiding elements + +Use the following table to hide elements from users, when appropriate. + +| Hide from sighted users | Hide from screen readers | Hide from both sighted and screen reader users | +| --- | --- | --- | +| `.gl-sr-only` | `aria-hidden="true"` | `display: none`, `visibility: hidden`, or `hidden` attribute | + +### Hide decorative images from screen readers + +To reduce noise for screen reader users, hide decorative images using `alt=""`. +If the image is not an `img` element, such as an inline SVG, you can hide it by adding both `role="img"` and `alt=""`. + +`gl-icon` components automatically hide their icons from screen readers so `aria-hidden="true"` is +unnecessary when using `gl-icon`. + +```html +// good - decorative images hidden from screen readers +<img src="decorative.jpg" alt=""> +<svg role="img" alt=""> +<gl-icon name="epic"/> +``` + +## When should ARIA be used + +No ARIA is required when using semantic HTML because it incorporates accessibility. + +However, there are some UI patterns and widgets that do not have semantic HTML equivalents. +Building such widgets require ARIA to make them understandable to screen readers. +Proper research and testing should be done to ensure compliance with ARIA. + +Ideally, these widgets would exist only in [GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/). +Use of ARIA would then only occur in [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/) and not [GitLab](https://gitlab.com/gitlab-org/gitlab/). ## Resources -[Chrome Accessibility Developer Tools](https://github.com/GoogleChrome/accessibility-developer-tools) -assist with testing for potential accessibility problems in GitLab. +### Viewing the browser accessibility tree + +- [Firefox DevTools guide](https://developer.mozilla.org/en-US/docs/Tools/Accessibility_inspector#accessing_the_accessibility_inspector) +- [Chrome DevTools guide](https://developers.google.com/web/tools/chrome-devtools/accessibility/reference#pane) + +### Browser extensions + +We have two options for Web accessibility testing: + +- [axe](https://www.deque.com/axe/) for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/) +- [axe](https://www.deque.com/axe/) for [Chrome](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd) -The [axe](https://www.deque.com/axe/) browser extension (available for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/) and [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd)) provides running audits and feedback on markup, CSS, and even potentially problematic color usages. +### Other links -Accessibility best-practices and more in-depth information are available on -[the Audit Rules page](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules) for the Chrome Accessibility Developer Tools. The [Awesome Accessibility](https://github.com/brunopulis/awesome-a11y) list is a compilation of accessibility-related material. +- [The A11Y Project](https://www.a11yproject.com/) is a good resource for accessibility +- [Awesome Accessibility](https://github.com/brunopulis/awesome-a11y) + is a compilation of accessibility-related material +- You can read [Chrome Accessibility Developer Tools'](https://github.com/GoogleChrome/accessibility-developer-tools) + rules on its [Audit Rules page](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules) diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md index c51f99ca9d2..afaf6df8f8a 100644 --- a/doc/development/fe_guide/architecture.md +++ b/doc/development/fe_guide/architecture.md @@ -17,6 +17,13 @@ when appropriate. You can find the Frontend Architecture experts on the [team page](https://about.gitlab.com/company/team/). +## Widget Architecture + +The [Plan stage](https://about.gitlab.com/handbook/engineering/development/dev/fe-plan/) +is refactoring the right sidebar to consist of **widgets**. They have a specific architecture to be +reusable and to expose an interface that can be used by external Vue applications on the page. +Learn more about the [widget architecture](widgets.md). + ## Examples You can find [documentation about the desired architecture](vue.md) for a new diff --git a/doc/development/fe_guide/dark_mode.md b/doc/development/fe_guide/dark_mode.md index dd7ffd1ee6c..34901bbb1e6 100644 --- a/doc/development/fe_guide/dark_mode.md +++ b/doc/development/fe_guide/dark_mode.md @@ -17,7 +17,7 @@ Note the following: - The dark mode palette is defined in `app/assets/stylesheets/themes/_dark.scss`. This is loaded _before_ application.scss to generate `application_dark.css` - We define two types of variables in `_dark.scss`: - - SCSS variables are used in framework, components, and utitlity classes. + - SCSS variables are used in framework, components, and utility classes. - CSS variables are used for any colors within the `app/assets/stylesheets/page_bundles` directory. - `app/views/layouts/_head.html.haml` then loads application or application_dark based on the user's theme preference. @@ -68,7 +68,7 @@ We [plan to add](https://gitlab.com/gitlab-org/gitlab/-/issues/301147) the CSS v ## When to use SCSS variables There are a few things we do in SCSS that we cannot (easily) do with CSS, such as the following -functions: +functions: - `lighten` - `darken` diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md index 8fe03544f85..bf46e8e16ce 100644 --- a/doc/development/fe_guide/dependencies.md +++ b/doc/development/fe_guide/dependencies.md @@ -20,7 +20,7 @@ This distinction is used by omnibus to determine which dependencies it requires Exceptions are made for some tools that we require in the `compile-production-assets` CI job such as `webpack-bundle-analyzer` to analyze our -production assets post-compile. +production assets post-compile. ## Updating dependencies diff --git a/doc/development/fe_guide/editor_lite.md b/doc/development/fe_guide/editor_lite.md index f783a97fbd3..5ad0c753ced 100644 --- a/doc/development/fe_guide/editor_lite.md +++ b/doc/development/fe_guide/editor_lite.md @@ -4,116 +4,141 @@ group: Editor 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 --- -# Editor Lite +# Editor Lite **(FREE)** -## Background +**Editor Lite** provides the editing experience at GitLab. This thin wrapper around +[the Monaco editor](https://microsoft.github.io/monaco-editor/) provides necessary +helpers and abstractions, and extends Monaco [using extensions](#extensions). Multiple +GitLab features use it, including: -**Editor Lite** is a technological product driving features like [Web Editor](../../user/project/repository/web_editor.md), [Snippets](../../user/snippets.md), and [CI Linter](../../ci/lint.md). Editor Lite is the driving technology for any single-file editing experience across the product. - -Editor Lite is a thin wrapper around [the Monaco editor](https://microsoft.github.io/monaco-editor/index.html) that provides the necessary helpers and abstractions and extends Monaco using extensions. +- [Web IDE](../../user/project/web_ide/index.md) +- [CI Linter](../../ci/lint.md) +- [Snippets](../../user/snippets.md) +- [Web Editor](../../user/project/repository/web_editor.md) ## How to use Editor Lite -Editor Lite is framework-agnostic and can be used in any application, whether it's Rails or Vue. For the convenience of integration, we have the dedicated `<editor-lite>` Vue component, but in general, the integration of Editor Lite is pretty straightforward: +Editor Lite is framework-agnostic and can be used in any application, including both +Rails and Vue. To help with integration, we have the dedicated `<editor-lite>` +Vue component, but the integration of Editor Lite is generally straightforward: 1. Import Editor Lite: -```javascript -import EditorLite from '~/editor/editor_lite'; -``` + ```javascript + import EditorLite from '~/editor/editor_lite'; + ``` 1. Initialize global editor for the view: -```javascript -const editor = new EditorLite({ - // Editor Options. - // The list of all accepted options can be found at - // https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html -}); -``` + ```javascript + const editor = new EditorLite({ + // Editor Options. + // The list of all accepted options can be found at + // https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html + }); + ``` 1. Create an editor's instance: -```javascript -editor.createInstance({ - // Editor Lite configuration options. -}) -``` + ```javascript + editor.createInstance({ + // Editor Lite configuration options. + }) + ``` An instance of Editor Lite accepts the following configuration options: | Option | Required? | Description | -| ---- | ---- | ---- | -| `el` | `true` | `HTML Node`: element on which to render the editor | -| `blobPath` | `false` | `String`: the name of a file to render in the editor. It is used to identify the correct syntax highlighter to use with that or another file type. Can accept wildcard as in `*.js` when the actual filename isn't known or doesn't play any role | -| `blobContent` | `false` | `String`: the initial content to be rendered in the editor | -| `extensions` | `false` | `Array`: extensions to use in this instance | -| `blobGlobalId` | `false` | `String`: auto-generated property.<br>**Note:** this prop might go away in the future. Do not pass `blobGlobalId` unless you know what you're doing.| -| [Editor Options](https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html) | `false` | `Object(s)`: any prop outside of the list above is treated as an Editor Option for this particular instance. This way, one can override global Editor Options on the instance level. | +| -------------- | ------- | ---- | +| `el` | `true` | `HTML Node`: The element on which to render the editor. | +| `blobPath` | `false` | `String`: The name of a file to render in the editor, used to identify the correct syntax highlighter to use with that file, or another file type. Can accept wildcards like `*.js` when the actual filename isn't known or doesn't play any role. | +| `blobContent` | `false` | `String`: The initial content to render in the editor. | +| `extensions` | `false` | `Array`: Extensions to use in this instance. | +| `blobGlobalId` | `false` | `String`: An auto-generated property.<br>**Note:** This property may go away in the future. Do not pass `blobGlobalId` unless you know what you're doing.| +| Editor Options | `false` | `Object(s)`: Any property outside of the list above is treated as an Editor Option for this particular instance. Use this field to override global Editor Options on the instance level. A full [index of Editor Options](https://microsoft.github.io/monaco-editor/api/enums/monaco.editor.editoroption.html) is available. | ## API -The editor follows the same public API as [provided by Monaco editor](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) with just a few additional functions on the instance level: +The editor uses the same public API as +[provided by Monaco editor](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) +with additional functions on the instance level: -| Function | Arguments | Description -| ----- | ----- | ----- | -| `updateModelLanguage` | `path`: String | Updates the instance's syntax highlighting to follow the extension of the passed `path`. Available only on _instance_ level| -| `use` | Array of objects | Array of **extensions** to apply to the instance. Accepts only the array of _objects_, which means that the extensions' ES6 modules should be fetched and resolved in your views/components before being passed to `use`. This prop is available on _instance_ (applies extension to this particular instance) and _global editor_ (applies the same extension to all instances) levels. | +| Function | Arguments | Description +| --------------------- | ----- | ----- | +| `updateModelLanguage` | `path`: String | Updates the instance's syntax highlighting to follow the extension of the passed `path`. Available only on the instance level.| +| `use` | Array of objects | Array of extensions to apply to the instance. Accepts only the array of _objects_. You must fetch the extensions' ES6 modules must be fetched and resolved in your views or components before they are passed to `use`. This property is available on _instance_ (applies extension to this particular instance) and _global editor_ (applies the same extension to all instances) levels. | | Monaco Editor options | See [documentation](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) | Default Monaco editor options | ## Tips 1. Editor's loading state. -Editor Lite comes with the loading state built-in, making spinners and loaders rarely needed in HTML. To benefit the built-in loading state, set the `data-editor-loading` property on the HTML element that is supposed to contain the editor. Editor Lite shows the loader automatically while it's bootstrapping. -![Editor Lite: loading state](img/editor_lite_loading.png) + The loading state is built in to Editor Lite, making spinners and loaders + rarely needed in HTML. To benefit the built-in loading state, set the `data-editor-loading` + property on the HTML element that should contain the editor. When bootstrapping, + Editor Lite shows the loader automatically. + + ![Editor Lite: loading state](img/editor_lite_loading.png) 1. Update syntax highlighting if the filename changes. -```javascript -// fileNameEl here is the HTML input element that contains the file name -fileNameEl.addEventListener('change', () => { - this.editor.updateModelLanguage(fileNameEl.value); -}); -``` + ```javascript + // fileNameEl here is the HTML input element that contains the file name + fileNameEl.addEventListener('change', () => { + this.editor.updateModelLanguage(fileNameEl.value); + }); + ``` 1. Get the editor's content. -We might set up listeners on the editor for every change but it rapidly can become an expensive operation. Instead , we can get editor's content when it's needed. For example on a form's submission: + We may set up listeners on the editor for every change, but it rapidly can become + an expensive operation. Instead, get the editor's content when it's needed. + For example, on a form's submission: -```javascript -form.addEventListener('submit', () => { - my_content_variable = this.editor.getValue(); -}); -``` + ```javascript + form.addEventListener('submit', () => { + my_content_variable = this.editor.getValue(); + }); + ``` 1. Performance -Even though Editor Lite itself is extremely slim, it still depends on Monaco editor. Monaco is not an easily tree-shakeable module. Hence, every time you add Editor Lite to a view, the JavaScript bundle's size significantly increases, affecting your view's loading performance. It is recommended to import the editor on demand on those views where it is not 100% certain that the editor is needed. Or if the editor is a secondary element of the view. Loading Editor Lite on demand is no different from loading any other module: + Even though Editor Lite itself is extremely slim, it still depends on Monaco editor, + which adds weight. Every time you add Editor Lite to a view, the JavaScript bundle's + size significantly increases, affecting your view's loading performance. We recommend + you import the editor on demand if either: -```javascript -someActionFunction() { - import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite'). - then(({ default: EditorLite }) => { - const editor = new EditorLite(); - ... - }); - ... -} -``` + - You're uncertain if the view needs the editor. + - The editor is a secondary element of the view. + + Loading Editor Lite on demand is handled like loading any other module: + + ```javascript + someActionFunction() { + import(/* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite'). + then(({ default: EditorLite }) => { + const editor = new EditorLite(); + ... + }); + ... + } + ``` ## Extensions -Editor Lite has been built to provide a universal, extensible editing tool to the whole product, -which would not depend on any particular group. Even though the Editor Lite's core is owned by +Editor Lite provides a universal, extensible editing tool to the whole product, +and doesn't depend on any particular group. Even though the Editor Lite's core is owned by [Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor/), -the main functional elements — extensions — can be owned by any group. Editor Lite extensions' main idea -is that the core of the editor remains very slim and stable. At the same time, whatever new functionality -is needed can be added as an extension to this core, without touching the core itself. Any group is allowed -to build and own new editing functionality without being afraid of it being broken or overridden with -the Editor Lite changes. +any group can own the extensions—the main functional elements. The goal of +Editor Lite extensions is to keep the editor's core slim and stable. Any +needed features can be added as extensions to this core. Any group can +build and own new editing features without worrying about changes to Editor Lite +breaking or overriding them. -Structurally, the complete implementation of Editor Lite could be presented as the following diagram: +You can depend on other modules in your extensions. This organization helps keep +the size of Editor Lite's core at bay by importing dependencies only when needed. + +Structurally, the complete implementation of Editor Lite can be presented as this diagram: ```mermaid graph TD; @@ -125,7 +150,7 @@ graph TD; A[Editor Lite]---Z[Monaco] ``` -Technically, an extension is just an ES6 module that exports a JavaScript object: +An extension is an ES6 module that exports a JavaScript object: ```javascript import { Position } from 'monaco-editor'; @@ -138,10 +163,9 @@ export default { ``` -Important things to note here: - -- We can depend on other modules in our extensions. This organization helps keep the size of Editor Lite's core at bay by importing dependencies only when needed. -- `this` in extension's functions refers to the current Editor Lite instance. Using `this`, you get access to the complete instance's API, such as the `setPosition()` method in this particular case. +In the extension's functions, `this` refers to the current Editor Lite instance. +Using `this`, you get access to the complete instance's API, such as the +`setPosition()` method in this particular case. ### Using an existing extension @@ -159,7 +183,11 @@ editor.use(MyExtension); ### Creating an extension -Let's create our first Editor Lite extension. Extensions are ES6 modules exporting a basic `Object` that is used to extend Editor Lite's functionality. As a test, let's create an extension that extends Editor Lite with a new function that, when called, outputs editor's content in `alert`. +Let's create our first Editor Lite extension. Extensions are +[ES6 modules](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/) exporting a +basic `Object`, used to extend Editor Lite's features. As a test, let's +create an extension that extends Editor Lite with a new function that, when called, +outputs the editor's content in `alert`. `~/my_folder/my_fancy_extension.js:` @@ -171,7 +199,10 @@ export default { }; ``` -And that's it with our extension! Note that we're using `this` as a reference to the instance. And through it, we get access to the complete underlying [Monaco editor API](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html) like `getValue()` in this case. +In the code example, `this` refers to the instance. By referring to the instance, +we can access the complete underlying +[Monaco editor API](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html), +which includes functions like `getValue()`. Now let's use our extension: @@ -191,7 +222,11 @@ someButton.addEventListener('click', () => { }); ``` -First of all, we import Editor Lite and our new extension. Then we create the editor and its instance. By default Editor Lite has no `throwContentAtMe` method. But the `editor.use(MyFancyExtension)` line brings that method to our instance. After that, we can use it any time we need it. In this case, we call it when some theoretical button has been clicked. +First of all, we import Editor Lite and our new extension. Then we create the +editor and its instance. By default Editor Lite has no `throwContentAtMe` method. +But the `editor.use(MyFancyExtension)` line brings that method to our instance. +After that, we can use it any time we need it. In this case, we call it when some +theoretical button has been clicked. This script would result in an alert containing the editor's content when `someButton` is clicked. @@ -201,27 +236,28 @@ This script would result in an alert containing the editor's content when `someB 1. Performance -Just like Editor Lite itself, any extension can be loaded on demand to not harm loading performance of the views: + Just like Editor Lite itself, any extension can be loaded on demand to not harm + loading performance of the views: -```javascript -const EditorPromise = import( - /* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite' -); -const MarkdownExtensionPromise = import('~/editor/editor_markdown_ext'); - -Promise.all([EditorPromise, MarkdownExtensionPromise]) - .then(([{ default: EditorLite }, { default: MarkdownExtension }]) => { - const editor = new EditorLite().createInstance({ - ... - }); - editor.use(MarkdownExtension); - }); -``` + ```javascript + const EditorPromise = import( + /* webpackChunkName: 'EditorLite' */ '~/editor/editor_lite' + ); + const MarkdownExtensionPromise = import('~/editor/editor_markdown_ext'); + + Promise.all([EditorPromise, MarkdownExtensionPromise]) + .then(([{ default: EditorLite }, { default: MarkdownExtension }]) => { + const editor = new EditorLite().createInstance({ + ... + }); + editor.use(MarkdownExtension); + }); + ``` 1. Using multiple extensions -Just pass the array of extensions to your `use` method: + Just pass the array of extensions to your `use` method: -```javascript -editor.use([FileTemplateExtension, MyFancyExtension]); -``` + ```javascript + editor.use([FileTemplateExtension, MyFancyExtension]); + ``` diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index a53d9fee029..2e812d9fa0a 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -63,6 +63,7 @@ see [Immutability and cache updates](#immutability-and-cache-updates) for more i If you use VS Code, the Apollo GraphQL extension supports autocompletion in `.graphql` files. To set up the GraphQL extension, follow these steps: +1. Generate the schema: `bundle exec rake gitlab:graphql:schema:dump` 1. Add an `apollo.config.js` file to the root of your `gitlab` local directory. 1. Populate the file with the following content: @@ -72,7 +73,7 @@ the GraphQL extension, follow these steps: includes: ['./app/assets/javascripts/**/*.graphql', './ee/app/assets/javascripts/**/*.graphql'], service: { name: 'GitLab', - localSchemaFile: './doc/api/graphql/reference/gitlab_schema.graphql', + localSchemaFile: './tmp/tests/graphql/gitlab_schema.graphql', }, }, }; @@ -422,7 +423,7 @@ query getAuthorData($authorNameEnabled: Boolean = false) { ``` Then in the Vue (or JavaScript) call to the query we can pass in our feature flag. This feature -flag needs to be already set up correctly. See the [feature flag documentation](../feature_flags/development.md) +flag needs to be already set up correctly. See the [feature flag documentation](../feature_flags/index.md) for the correct way to do this. ```javascript @@ -768,6 +769,23 @@ export default { ### Testing +#### Generating the GraphQL schema + +Some of our tests load the schema JSON files. To generate these files, run: + +```shell +bundle exec rake gitlab:graphql:schema:dump +``` + +You should run this task after pulling from upstream, or when rebasing your +branch. This is run automatically as part of `gdk update`. + +NOTE: +If you use the RubyMine IDE, and have marked the `tmp` directory as +"Excluded", you should "Mark Directory As -> Not Excluded" for +`gitlab/tmp/tests/graphql`. This will allow the **JS GraphQL** plugin to +automatically find and index the schema. + #### Mocking response as component data <!-- vale gitlab.Spelling = NO --> @@ -1093,6 +1111,45 @@ it('calls a mutation with correct parameters and reorders designs', async () => }); ``` +To mock multiple query response states, success and failure, Apollo Client's native retry behavior can combine with Jest's mock functions to create a series of responses. These do not need to be advanced manually, but they do need to be awaited in specific fashion. + +```javascript +describe('when query times out', () => { + const advanceApolloTimers = async () => { + jest.runOnlyPendingTimers(); + await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick(); + }; + + beforeEach(async () => { + const failSucceedFail = jest + .fn() + .mockResolvedValueOnce({ errors: [{ message: 'timeout' }] }) + .mockResolvedValueOnce(mockPipelineResponse) + .mockResolvedValueOnce({ errors: [{ message: 'timeout' }] }); + + createComponentWithApollo(failSucceedFail); + await wrapper.vm.$nextTick(); + }); + + it('shows correct errors and does not overwrite populated data when data is empty', async () => { + /* fails at first, shows error, no data yet */ + expect(getAlert().exists()).toBe(true); + expect(getGraph().exists()).toBe(false); + + /* succeeds, clears error, shows graph */ + await advanceApolloTimers(); + expect(getAlert().exists()).toBe(false); + expect(getGraph().exists()).toBe(true); + + /* fails again, alert retuns but data persists */ + await advanceApolloTimers(); + expect(getAlert().exists()).toBe(true); + expect(getGraph().exists()).toBe(true); + }); +}); +``` + #### Testing `@client` queries ##### Using mock resolvers diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md index 711c6a5f875..1315520342e 100644 --- a/doc/development/fe_guide/index.md +++ b/doc/development/fe_guide/index.md @@ -104,7 +104,7 @@ See the relevant style guides for our guidelines and for information on linting: - [JavaScript](style/javascript.md). Our guide is based on the excellent [Airbnb](https://github.com/airbnb/javascript) style guide with a few small changes. -- [SCSS](style/scss.md): our SCSS conventions which are enforced through [`scss-lint`](https://github.com/sds/scss-lint). +- [SCSS](style/scss.md): [our SCSS conventions](https://gitlab.com/gitlab-org/frontend/gitlab-stylelint-config) which are enforced through [`stylelint`](https://stylelint.io). - [HTML](style/html.md). Guidelines for writing HTML code consistent with the rest of the codebase. - [Vue](style/vue.md). Guidelines and conventions for Vue code may be found here. diff --git a/doc/development/fe_guide/keyboard_shortcuts.md b/doc/development/fe_guide/keyboard_shortcuts.md index e50e9ec65df..aab252da305 100644 --- a/doc/development/fe_guide/keyboard_shortcuts.md +++ b/doc/development/fe_guide/keyboard_shortcuts.md @@ -33,9 +33,10 @@ Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), togglePerformanceBar); ## Shortcut customization `keybindings.js` stores keyboard shortcut customizations as a JSON string in -`localStorage`. When `keybindings.js` is first imported, it fetches any -customizations from `localStorage` and merges these customizations into the -default set of keybindings. There is no UI to edit these customizations. +`localStorage`. When `keysFor` is called, it uses the provided command object's +`id` to lookup any customizations found in `localStorage` and returns the custom +keybindings, or the default keybindings if the command has not been customized. +There is no UI to edit these customizations. ## Adding new shortcuts @@ -44,27 +45,33 @@ developers are encouraged to build _lots_ of keyboard shortcuts into GitLab. Shortcuts that are less likely to be used should be [disabled](#disabling-shortcuts) by default. -To add a new shortcut, define and export a new command string in +To add a new shortcut, define and export a new command object in `keybindings.js`: ```javascript -export const MAKE_COFFEE = 'foodAndBeverage.makeCoffee'; +export const MAKE_COFFEE = { + id: 'foodAndBeverage.makeCoffee', + description: s__('KeyboardShortcuts|Make coffee'), + defaultKeys: ['mod+shift+c'], +}; ``` -Next, add a new command definition under the appropriate group in the -`keybindingGroups` array: +Next, add a new command to the appropriate keybinding group object: ```javascript -{ - description: s__('KeyboardShortcuts|Make coffee'), - command: MAKE_COFFEE, - defaultKeys: ['mod+shift+c'], - customKeys: customizations[MAKE_COFFEE], +const COFFEE_GROUP = { + id: 'foodAndBeverage', + name: s__('KeyboardShortcuts|Food and Beverage'), + keybindings: [ + MAKE_ESPRESSO, + MAKE_LATTE, + MAKE_COFFEE + ]; } ``` Finally, in the application code, import the `keysFor` function and the new -command and bind the shortcut to the handler using Mousetrap: +command object and bind the shortcut to the handler using Mousetrap: ```javascript import { keysFor, MAKE_COFFEE } from '~/behaviors/shortcuts/keybindings' @@ -81,16 +88,34 @@ shortcut to an empty array `[]`. For example, to introduce a new shortcut that is disabled by default, a command can be defined like this: ```javascript -export const MAKE_MOCHA = 'foodAndBeverage.makeMocha'; - -{ +export const MAKE_MOCHA = { + id: 'foodAndBeverage.makeMocha', description: s__('KeyboardShortcuts|Make a mocha'), - command: MAKE_MOCHA, defaultKeys: [], - customKeys: customizations[MAKE_MOCHA], -} +}; ``` +## Making shortcuts non-customizable + +Occasionally, it's important that a keyboard shortcut _not_ be customizable +(although this should be a rare occurrence). + +In this case, a shortcut can be defined with `customizable: false`, which +disables customization of the keybinding: + +```javascript +export const MAKE_AMERICANO = { + id: 'foodAndBeverage.makeAmericano', + description: s__('KeyboardShortcuts|Make an Americano'), + defaultKeys: ['mod+shift+a'], + + // this disables customization of this shortcut + customizable: false +}; +``` + +This shortcut will always be bound to its `defaultKeys`. + ## Make cross-platform shortcuts It's difficult to make shortcuts that work well in all platforms and browsers. diff --git a/doc/development/fe_guide/security.md b/doc/development/fe_guide/security.md index df4613d521d..1a6646df877 100644 --- a/doc/development/fe_guide/security.md +++ b/doc/development/fe_guide/security.md @@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Resources -[Mozilla’s HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli) and +[Mozilla’s HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli) and [Qualys SSL Labs Server Test](https://www.ssllabs.com/ssltest/analyze.html) are good resources for finding potential problems and ensuring compliance with security best practices. @@ -105,3 +105,9 @@ element.appendChild(sanitize(unsafeHtml)); This `sanitize` function takes the same configuration as the original. + +### Fixing Security Issues + +When refactoring old code, it's important that we don't accidentally remove specs written to catch security issues which might still be relevant. + +We should mark specs with `#security` in either the `describe` or `it` blocks to communicate to the engineer reading the code that by removing these specs could have severe consequences down the road, and you are removing code that could catch a reintroduction of a security issue. diff --git a/doc/development/fe_guide/style/html.md b/doc/development/fe_guide/style/html.md index e53686de1a0..18f72a9655c 100644 --- a/doc/development/fe_guide/style/html.md +++ b/doc/development/fe_guide/style/html.md @@ -6,6 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w # HTML style guide +See also our [accessibility page](../accessibility.md). + ## Semantic elements [Semantic elements](https://developer.mozilla.org/en-US/docs/Glossary/Semantics) are HTML tags that @@ -52,30 +54,27 @@ Button tags requires a `type` attribute according to the [W3C HTML specification <button type="button"></button> ``` -### Button role - -If an HTML element has an `onClick` handler but is not a button, it should have `role="button"`. This is [more accessible](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role). - -```html -// bad -<div onClick="doSomething"></div> - -// good -<div role="button" onClick="doSomething"></div> -``` - ## Links ### Blank target +Avoid forcing links to open in a new window as this reduces the control the user has over the link. +However, it might be a good idea to use a blank target when replacing the current page with +the link makes the user lose content or progress. + Use `rel="noopener noreferrer"` whenever your links open in a new window, i.e. `target="_blank"`. This prevents a security vulnerability [documented by JitBit](https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/). +When using `gl-link`, using `target="_blank"` is sufficient as it automatically adds `rel="noopener noreferrer"` to the link. + ```html // bad <a href="url" target="_blank"></a> // good <a href="url" target="_blank" rel="noopener noreferrer"></a> + +// good +<gl-link href="url" target="_blank"></gl-link> ``` ### Fake links diff --git a/doc/development/fe_guide/style/index.md b/doc/development/fe_guide/style/index.md index 89a3d874184..f3da78647be 100644 --- a/doc/development/fe_guide/style/index.md +++ b/doc/development/fe_guide/style/index.md @@ -16,7 +16,7 @@ changes. ## SCSS style guide -Our [SCSS conventions](scss.md) which are enforced through [`scss-lint`](https://github.com/sds/scss-lint). +Our [SCSS conventions](scss.md) which are enforced through [`stylelint`](https://stylelint.io). ## HTML style guide diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md index 5c35b880eab..334372af1f4 100644 --- a/doc/development/fe_guide/style/javascript.md +++ b/doc/development/fe_guide/style/javascript.md @@ -14,7 +14,7 @@ In addition to the style guidelines set by Airbnb, we also have a few specific r listed below. NOTE: -You can run ESLint locally by running `yarn eslint` +You can run ESLint locally by running `yarn run lint:eslint:all` or `yarn run lint:eslint $PATH_TO_FILE`. ## Avoid forEach @@ -294,3 +294,24 @@ Strive to write many small pure functions and minimize where mutations occur var c = pureFunction(values.foo); ``` + +## Export constants as primitives + +Prefer exporting constant primitives with a common namespace over exporting objects. This allows for better compile-time reference checks and helps to avoid accidential `undefined`s at runtime. In addition, it helps in reducing bundle sizes. + +Only export the constants as a collection (array, or object) when there is a need to iterate over them, for instance, for a prop validator. + + ```javascript + // bad + export const VARIANT = { + WARNING: 'warning', + ERROR: 'error', + }; + + // good + export const VARIANT_WARNING = 'warning'; + export const VARIANT_ERROR = 'error'; + + // good, if the constants need to be iterated over + export const VARIANTS = [VARIANT_WARNING, VARIANT_ERROR]; + ``` diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md index 1d0b3c2b7fc..c0817626360 100644 --- a/doc/development/fe_guide/style/scss.md +++ b/doc/development/fe_guide/style/scss.md @@ -99,7 +99,7 @@ ul { // Best // prefer an existing utility class over adding existing styles -```0 +``` Class names are also preferable to IDs. Rules that use IDs are not-reusable, as there can only be one affected element on @@ -132,16 +132,14 @@ Before adding a new variable for a color or a size, guarantee: ## Linting -We use [SCSS Lint](https://github.com/sds/scss-lint) to check for style guide conformity. It uses the -ruleset in `.scss-lint.yml`, which is located in the home directory of the -project. +We use [stylelint](https://stylelint.io) to check for style guide conformity. It uses the +ruleset in `.stylelintrc` and rules from [our SCSS configuration](https://gitlab.com/gitlab-org/frontend/gitlab-stylelint-config). `.stylelintrc` is located in the home directory of the project. -To check if any warnings are produced by your changes, run `rake -scss_lint` in the GitLab directory. SCSS Lint also runs in GitLab CI/CD to +To check if any warnings are produced by your changes, run `yarn lint:stylelint` in the GitLab directory. Stylelint also runs in GitLab CI/CD to catch any warnings. If the Rake task is throwing warnings you don't understand, SCSS Lint's -documentation includes [a full list of their linters](https://github.com/sds/scss-lint/blob/master/lib/scss_lint/linter/README.md). +documentation includes [a full list of their rules](https://stylelint.io/user-guide/rules/list). ### Fixing issues diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md index 0288238a9e5..d62145b4a4c 100644 --- a/doc/development/fe_guide/style/vue.md +++ b/doc/development/fe_guide/style/vue.md @@ -432,41 +432,7 @@ must be unique. It's advised to use `kebab-case` namespaces. Useful links: 1. [`key`](https://vuejs.org/v2/guide/list.html#key) -1. [Vue Style Guide: Keyed v-for](https://vuejs.org/v2/style-guide/#Keyed-v-for-essential ) - -## Vue and Bootstrap - -1. Tooltips: Do not rely on `has-tooltip` class name for Vue components - - ```html - // bad - <span - class="has-tooltip" - title="Some tooltip text"> - Text - </span> - - // good - <span - v-tooltip - title="Some tooltip text"> - Text - </span> - ``` - -1. Tooltips: When using a tooltip, include the tooltip directive, `./app/assets/javascripts/vue_shared/directives/tooltip.js` - -1. Don't change `data-original-title`. - - ```html - // bad - <span data-original-title="tooltip text">Foo</span> - - // good - <span title="tooltip text">Foo</span> - - $('span').tooltip('_fixTitle'); - ``` +1. [Vue Style Guide: Keyed v-for](https://vuejs.org/v2/style-guide/#Keyed-v-for-essential) ## Vue testing diff --git a/doc/development/fe_guide/tooling.md b/doc/development/fe_guide/tooling.md index 7a2d8fccdbf..1ab97d8a1f5 100644 --- a/doc/development/fe_guide/tooling.md +++ b/doc/development/fe_guide/tooling.md @@ -17,7 +17,7 @@ This section describes yarn scripts that are available to validate and apply aut To check all staged files (based on `git diff`) with ESLint, run the following script: ```shell -yarn eslint-staged +yarn run lint:eslint:staged ``` A list of problems found are logged to the console. @@ -25,15 +25,21 @@ A list of problems found are logged to the console. To apply automatic ESLint fixes to all staged files (based on `git diff`), run the following script: ```shell -yarn eslint-staged-fix +yarn run lint:eslint:staged:fix ``` If manual changes are required, a list of changes are sent to the console. +To check a specific file in the repository with ESLINT, run the following script (replacing $PATH_TO_FILE): + +```shell +yarn run lint:eslint $PATH_TO_FILE +``` + To check **all** files in the repository with ESLint, run the following script: ```shell -yarn eslint +yarn run lint:eslint:all ``` A list of problems found are logged to the console. @@ -41,7 +47,7 @@ A list of problems found are logged to the console. To apply automatic ESLint fixes to **all** files in the repository, run the following script: ```shell -yarn eslint-fix +yarn run lint:eslint:all:fix ``` If manual changes are required, a list of changes are sent to the console. @@ -98,6 +104,57 @@ When declaring multiple globals, always use one `/* global [name] */` line per v /* global jQuery */ ``` +### Deprecating functions with `import/no-deprecated` + +Our `@gitlab/eslint-plugin` Node module contains the [`eslint-plugin-import`](https://gitlab.com/gitlab-org/frontend/eslint-plugin) package. + +We can use the [`import/no-deprecated`](https://github.com/benmosher/eslint-plugin-import/blob/HEAD/docs/rules/no-deprecated.md) rule to deprecate functions using a JSDoc block with a `@deprecated` tag: + +```javascript +/** + * Convert search query into an object + * + * @param {String} query from "document.location.search" + * @param {Object} options + * @param {Boolean} options.gatherArrays - gather array values into an Array + * @returns {Object} + * + * ex: "?one=1&two=2" into {one: 1, two: 2} + * @deprecated Please use `queryToObject` instead. See https://gitlab.com/gitlab-org/gitlab/-/issues/283982 for more information + */ +export function queryToObject(query, options = {}) { + ... +} +``` + +It is strongly encouraged that you: + +- Put in an **alternative path for developers** looking to use this function. +- **Provide a link to the issue** that tracks the migration process. + +NOTE: +Uses are detected if you import the deprecated function into another file. They are not detected when the function is used in the same file. + +Running `$ yarn eslint` after this will give us the list of deprecated usages: + +```shell +$ yarn eslint + +./app/assets/javascripts/issuable_form.js + 9:10 error Deprecated: Please use `queryToObject` instead. See https://gitlab.com/gitlab-org/gitlab/-/issues/283982 for more information import/no-deprecated + 33:23 error Deprecated: Please use `queryToObject` instead. See https://gitlab.com/gitlab-org/gitlab/-/issues/283982 for more information import/no-deprecated +... +``` + +Grep for disabled cases of this rule to generate a working list to create issues from, so you can track the effort of removing deprecated uses: + +```shell +$ grep "eslint-disable.*import/no-deprecated" -r . + +./app/assets/javascripts/issuable_form.js:import { queryToObject, objectToQuery } from './lib/utils/url_utility'; // eslint-disable-line import/no-deprecate +./app/assets/javascripts/issuable_form.js: // eslint-disable-next-line import/no-deprecated +``` + ## Formatting with Prettier > Support for `.graphql` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227280) in GitLab 13.2. @@ -125,44 +182,28 @@ Please take care that you only let Prettier format the same file types as the gl The following yarn scripts are available to do global formatting: ```shell -yarn prettier-staged-save +yarn run lint:prettier:staged:fix ``` Updates all staged files (based on `git diff`) with Prettier and saves the needed changes. ```shell -yarn prettier-staged +yarn run lint:prettier:staged ``` Checks all staged files (based on `git diff`) with Prettier and log which files would need manual updating to the console. ```shell -yarn prettier-all +yarn run lint:prettier ``` Checks all files with Prettier and logs which files need manual updating to the console. ```shell -yarn prettier-all-save -``` - -Formats all files in the repository with Prettier. (This should only be used to test global rule updates otherwise you would end up with huge MR's). - -The source of these Yarn scripts can be found in `/scripts/frontend/prettier.js`. - -#### Scripts during Conversion period - -```shell -node ./scripts/frontend/prettier.js check-all ./vendor/ -``` - -This iterates over all files in a specific folder, and checks them. - -```shell -node ./scripts/frontend/prettier.js save-all ./vendor/ +yarn run lint:prettier:fix ``` -This iterates over all files in a specific folder and saves them. +Formats all files in the repository with Prettier. ### VSCode Settings diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md index abaf9cd68c7..250fe5106d3 100644 --- a/doc/development/fe_guide/troubleshooting.md +++ b/doc/development/fe_guide/troubleshooting.md @@ -39,3 +39,30 @@ See [this video](https://youtu.be/-BkEhghP-kM) for an in-depth overview and inve ``` Please note that `toMatchObject` actually changes the nature of the assertion and won't fail if some items are **missing** from the expectation. + +### Script issues + +## `core-js` errors when running scripts within the GitLab repository + +The following command assumes you've set up the GitLab repository in the +`~/workspace/gdk` directory. When running scripts within the GitLab repository, +such as code transformations, you might run into issues with `core-js` like this: + +```shell +~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:7 +$({ +^ +TypeError: $ is not a function + at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:6:1) + at Module._compile (internal/modules/cjs/loader.js:1063:30) + at Module._compile (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:99:24) + at Module._extensions..js (internal/modules/cjs/loader.js:1092:10) + at Object.newLoader [as .js] (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:104:7) + at Module.load (internal/modules/cjs/loader.js:928:32) + at Function.Module._load (internal/modules/cjs/loader.js:769:14) + at Module.require (internal/modules/cjs/loader.js:952:19) + at require (internal/modules/cjs/helpers.js:88:18) + at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/esnext.global-this.js:2:1) +``` + +**Remedy - Try moving the script into a separate repository and point to it to files in the GitLab repository** diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index 5b902e1b16e..220a4a107aa 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -237,6 +237,9 @@ Each Vue component has a unique output. This output is always present in the ren Although each method of a Vue component can be tested individually, our goal is to test the output of the render function, which represents the state at all times. +Visit the [Vue testing guide](https://vuejs.org/v2/guide/testing.html#Unit-Testing) for help +testing the rendered output. + Here's an example of a well structured unit test for [this Vue component](#appendix---vue-component-subject-under-test): ```javascript @@ -331,11 +334,6 @@ describe('~/todos/app.vue', () => { }); ``` -### Test the component's output - -The main return value of a Vue component is the rendered output. In order to test the component we -need to test the rendered output. Visit the [Vue testing guide](https://vuejs.org/v2/guide/testing.html#Unit-Testing). - ### Child components 1. Test any directive that defines if/how child component is rendered (for example, `v-if` and `v-for`). diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md index cc1d9ccab77..d44ab64ae5d 100644 --- a/doc/development/fe_guide/vuex.md +++ b/doc/development/fe_guide/vuex.md @@ -440,12 +440,11 @@ components, we need to include the store and provide the correct state: //component_spec.js import Vue from 'vue'; import Vuex from 'vuex'; -import { mount, createLocalVue } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import { createStore } from './store'; import Component from './component.vue' -const localVue = createLocalVue(); -localVue.use(Vuex); +Vue.use(Vuex); describe('component', () => { let store; @@ -455,7 +454,6 @@ describe('component', () => { store = createStore(); wrapper = mount(Component, { - localVue, store, }); }; @@ -483,6 +481,11 @@ describe('component', () => { }); ``` +Some test files may still use the +[deprecated `createLocalVue` function](https://gitlab.com/gitlab-org/gitlab/-/issues/220482) +from `@vue/test-utils` and `localVue.use(Vuex)`. This is unnecessary, and should be +avoided or removed when possible. + ### Two way data binding When storing form data in Vuex, it is sometimes necessary to update the value stored. The store diff --git a/doc/development/fe_guide/widgets.md b/doc/development/fe_guide/widgets.md new file mode 100644 index 00000000000..02876afe597 --- /dev/null +++ b/doc/development/fe_guide/widgets.md @@ -0,0 +1,143 @@ +--- +stage: none +group: unassigned +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 +--- + +# Widgets + +Frontend widgets are standalone Vue applications or Vue component trees that can be added on a page +to handle a part of the functionality. + +Good examples of widgets are [sidebar assignees](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue) and [sidebar confidentiality](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue). + +When building a widget, we should follow a few principles described below. + +## Vue Apollo is required + +All widgets should use the same stack (Vue + Apollo Client). +To make it happen, we must add Vue Apollo to the application root (if we use a widget +as a component) or provide it directly to a widget. For sidebar widgets, use the +[sidebar Apollo Client and Apollo Provider](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/sidebar/graphql.js): + +```javascript +import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue'; +import { apolloProvider } from '~/sidebar/graphql'; + +function mountConfidentialComponent() { + new Vue({ + apolloProvider, + components: { + SidebarConfidentialityWidget, + }, + /* ... */ + }); +} +``` + +## Required injections + +All editable sidebar widgets should use [`SidebarEditableItem`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue) to handle collapsed/expanded state. This component requires the `canUpdate` property provided in the application root. + +## No global state mappings + +We aim to make widgets as reusable as possible. That's why we should avoid adding any external state +bindings to widgets or to their child components. This includes Vuex mappings and mediator stores. + +## Widget's responsibility + +A widget is responsible for fetching and updating an entity it's designed for (assignees, iterations, and so on). +This means a widget should **always** fetch data (if it's not in Apollo cache already). +Even if we provide an initial value to the widget, it should perform a GraphQL query in the background +to be stored in Apollo cache. + +Eventually, when we have an Apollo Client cache as a global application state, we won't need to pass +initial data to the sidebar widget. Then it will be capable of retrieving the data from the cache. + +## Using GraphQL queries and mutations + +We need widgets to be flexible to work with different entities (epics, issues, merge requests, and so on). +Because we need different GraphQL queries and mutations for different sidebars, we create +[_mappings_](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/sidebar/constants.js#L9): + +```javascript +export const assigneesQueries = { + [IssuableType.Issue]: { + query: getIssueParticipants, + mutation: updateAssigneesMutation, + }, + [IssuableType.MergeRequest]: { + query: getMergeRequestParticipants, + mutation: updateMergeRequestParticipantsMutation, + }, +}; +``` + +To handle the same logic for query updates, we **alias** query fields. For example: + +- `group` or `project` become `workspace` +- `issue`, `epic`, or `mergeRequest` become `issuable` + +Unfortunately, Apollo assigns aliased fields a typename of `undefined`, so we need to fetch `__typename` explicitly: + +```plaintext +query issueConfidential($fullPath: ID!, $iid: String) { + workspace: project(fullPath: $fullPath) { + __typename + issuable: issue(iid: $iid) { + __typename + id + confidential + } + } +} +``` + +## Communication with other Vue applications + +If we need to communicate the changes of the widget state (for example, after successful mutation) +to the parent application, we should emit an event: + +```javascript +updateAssignees(assigneeUsernames) { + return this.$apollo + .mutate({ + mutation: this.$options.assigneesQueries[this.issuableType].mutation, + variables: {...}, + }) + .then(({ data }) => { + const assignees = data.issueSetAssignees?.issue?.assignees?.nodes || []; + this.$emit('assignees-updated', assignees); + }) +} +``` + +Sometimes, we want to listen to the changes on the different Vue application like `NotesApp`. +In this case, we can use a renderless component that imports a client and listens to a certain query: + +```javascript +import { fetchPolicies } from '~/lib/graphql'; +import { confidentialityQueries } from '~/sidebar/constants'; +import { defaultClient as gqlClient } from '~/sidebar/graphql'; + +created() { + if (this.issuableType !== IssuableType.Issue) { + return; + } + + gqlClient + .watchQuery({ + query: confidentialityQueries[this.issuableType].query, + variables: {...}, + fetchPolicy: fetchPolicies.CACHE_ONLY, + }) + .subscribe((res) => { + this.setConfidentiality(issuable.confidential); + }); +}, +methods: { + ...mapActions(['setConfidentiality']), +}, +``` + +[View an example of such a component.](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/notes/components/sidebar_subscription.vue) diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md index 21ac152c469..fc327a2defc 100644 --- a/doc/development/feature_flags/controls.md +++ b/doc/development/feature_flags/controls.md @@ -36,7 +36,7 @@ easier to measure the impact of both separately. The GitLab feature library (using [Flipper](https://github.com/jnunemaker/flipper), and covered in the [Feature -Flags process](process.md) guide) supports rolling out changes to a percentage of +Flags process](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle) guide) supports rolling out changes to a percentage of time to users. This in turn can be controlled using [GitLab ChatOps](../../ci/chatops/index.md). For an up to date list of feature flag commands please see [the source @@ -240,7 +240,7 @@ To disable a feature flag that has been enabled for a specific project you can r /chatops run feature set --group=gitlab-org some_feature false ``` -You cannot selectively disable feature flags for a specific project/group/user without applying a [specific method of implementing](development.md#selectively-disable-by-actor) the feature flags. +You cannot selectively disable feature flags for a specific project/group/user without applying a [specific method of implementing](index.md#selectively-disable-by-actor) the feature flags. ### Feature flag change logging @@ -276,17 +276,19 @@ and reduces confidence in our testing suite covering all possible combinations. Additionally, a feature flag overwritten in some of the environments can result in undefined and untested system behavior. -To remove a feature flag: +To remove a feature flag, open **one merge request** to make the changes. In the MR: -1. Open a new merge request with the ~"feature flag" label so - release managers are aware the changes are hidden behind a feature flag. +1. Add the ~"feature flag" label so release managers are aware the changes are hidden behind a feature flag. 1. If the merge request has to be picked into a stable branch, add the appropriate `~"Pick into X.Y"` label, for example `~"Pick into 13.0"`. - See [the feature flag process](process.md#including-a-feature-behind-feature-flag-in-the-final-release) + See [the feature flag process](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle#including-a-feature-behind-feature-flag-in-the-final-release) for further details. -1. Remove all references to the feature flag from the codebase. +1. Remove all references to the feature flag from the codebase, including tests. 1. Remove the YAML definition for the feature from the repository. -1. Clean up the feature flag from all environments with `/chatops run feature delete some_feature`. + +Once the above MR has been merged, you should: + +1. [Clean up the feature flag from all environments](#cleanup-chatops) with `/chatops run feature delete some_feature`. 1. Close the rollout issue for the feature flag after the feature flag is removed from the codebase. ### Cleanup ChatOps diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md index 0cdfa3e68d7..79efd6d5502 100644 --- a/doc/development/feature_flags/development.md +++ b/doc/development/feature_flags/development.md @@ -1,593 +1,7 @@ --- -type: reference, dev -stage: none -group: Development -info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines" +redirect_to: 'index.md' --- -# Developing with feature flags - -This document provides guidelines on how to use feature flags -in the GitLab codebase to conditionally enable features -and test them. - -Features that are developed and merged behind a feature flag -should not include a changelog entry. The entry should be added either in the merge -request removing the feature flag or the merge request where the default value of -the feature flag is set to enabled. If the feature contains any database migrations, it -*should* include a changelog entry for the database changes. - -WARNING: -All newly-introduced feature flags should be [disabled by default](process.md#feature-flags-in-gitlab-development). - -NOTE: -This document is the subject of continued work as part of an epic to [improve internal usage of Feature Flags](https://gitlab.com/groups/gitlab-org/-/epics/3551). Raise any suggestions as new issues and attach them to the epic. - -## Risk of a broken master (main) branch - -Feature flags **must** be used in the MR that introduces them. Not doing so causes a -[broken master](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) scenario due -to the `rspec:feature-flags` job that only runs on the `master` branch. - -## Types of feature flags - -Choose a feature flag type that matches the expected usage. - -### `development` type - -`development` feature flags are short-lived feature flags, -used so that unfinished code can be deployed in production. - -A `development` feature flag should have a rollout issue, -ideally created using the [Feature Flag Roll Out template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md). - -This is the default type used when calling `Feature.enabled?`. - -### `ops` type - -`ops` feature flags are long-lived feature flags that control operational aspects -of GitLab product behavior. For example, feature flags that disable features that might -have a performance impact, like special Sidekiq worker behavior. - -`ops` feature flags likely do not have rollout issues, as it is hard to -predict when they are enabled or disabled. - -To use `ops` feature flags, you must append `type: :ops` to `Feature.enabled?` -invocations: - -```ruby -# Check if feature flag is enabled -Feature.enabled?(:my_ops_flag, project, type: :ops) - -# Check if feature flag is disabled -Feature.disabled?(:my_ops_flag, project, type: :ops) - -# Push feature flag to Frontend -push_frontend_feature_flag(:my_ops_flag, project, type: :ops) -``` - -### `experiment` type - -`experiment` feature flags are used for A/B testing on GitLab.com. - -An `experiment` feature flag should conform to the same standards as a `development` feature flag, -although the interface has some differences. More information can be found in the [experiment guide](../experiment_guide/index.md). - -## Feature flag definition and validation - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229161) in GitLab 13.3. - -During development (`RAILS_ENV=development`) or testing (`RAILS_ENV=test`) all feature flag usage is being strictly validated. - -This process is meant to ensure consistent feature flag usage in the codebase. All feature flags **must**: - -- Be known. Only use feature flags that are explicitly defined. -- Not be defined twice. They have to be defined either in FOSS or EE, but not both. -- Use a valid and consistent `type:` across all invocations. -- Use the same `default_enabled:` across all invocations. -- Have an owner. - -All feature flags known to GitLab are self-documented in YAML files stored in: - -- [`config/feature_flags`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/feature_flags) -- [`ee/config/feature_flags`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/config/feature_flags) - -Each feature flag is defined in a separate YAML file consisting of a number of fields: - -| Field | Required | Description | -|---------------------|----------|----------------------------------------------------------------| -| `name` | yes | Name of the feature flag. | -| `type` | yes | Type of feature flag. | -| `default_enabled` | yes | The default state of the feature flag that is strictly validated, with `default_enabled:` passed as an argument. | -| `introduced_by_url` | no | The URL to the Merge Request that introduced the feature flag. | -| `rollout_issue_url` | no | The URL to the Issue covering the feature flag rollout. | -| `group` | no | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the feature flag. | - -NOTE: -All validations are skipped when running in `RAILS_ENV=production`. - -## Create a new feature flag - -The GitLab codebase provides [`bin/feature-flag`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/bin/feature-flag), -a dedicated tool to create new feature flag definitions. -The tool asks various questions about the new feature flag, then creates -a YAML definition in `config/feature_flags` or `ee/config/feature_flags`. - -Only feature flags that have a YAML definition file can be used when running the development or testing environments. - -```shell -$ bin/feature-flag my_feature_flag ->> Specify the group introducing the feature flag, like `group::apm`: -?> group::memory - ->> URL of the MR introducing the feature flag (enter to skip): -?> https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38602 - ->> Open this URL and fill in the rest of the details: -https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue%5Btitle%5D=%5BFeature+flag%5D+Rollout+of+%60test-flag%60&issuable_template=Feature+Flag+Roll+Out - ->> URL of the rollout issue (enter to skip): -?> https://gitlab.com/gitlab-org/gitlab/-/issues/232533 -create config/feature_flags/development/my_feature_flag.yml ---- -name: my_feature_flag -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38602 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232533 -group: group::memory -type: development -default_enabled: false -``` - -NOTE: -To create a feature flag that is only used in EE, add the `--ee` flag: `bin/feature-flag --ee` - -## Delete a feature flag - -See [cleaning up feature flags](controls.md#cleaning-up) for more information about -deleting feature flags. - -## Develop with a feature flag - -There are two main ways of using Feature Flags in the GitLab codebase: - -- [Backend code (Rails)](#backend) -- [Frontend code (VueJS)](#frontend) - -### Backend - -The feature flag interface is defined in [`lib/feature.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/feature.rb). -This interface provides a set of methods to check if the feature flag is enabled or disabled: - -```ruby -if Feature.enabled?(:my_feature_flag, project) - # execute code if feature flag is enabled -else - # execute code if feature flag is disabled -end - -if Feature.disabled?(:my_feature_flag, project) - # execute code if feature flag is disabled -end -``` - -In rare cases you may want to make a feature enabled by default. If so, explain the reasoning -in the merge request. Use `default_enabled: true` when checking the feature flag state: - -```ruby -if Feature.enabled?(:feature_flag, project, default_enabled: true) - # execute code if feature flag is enabled -else - # execute code if feature flag is disabled -end - -if Feature.disabled?(:my_feature_flag, project, default_enabled: true) - # execute code if feature flag is disabled -end -``` - -If not specified, `default_enabled` is `false`. - -To force reading the `default_enabled` value from the relative YAML definition file, use -`default_enabled: :yaml`: - -```ruby -if Feature.enabled?(:feature_flag, project, default_enabled: :yaml) - # execute code if feature flag is enabled -end -``` - -```ruby -if Feature.disabled?(:feature_flag, project, default_enabled: :yaml) - # execute code if feature flag is disabled -end -``` - -This allows to use the same feature flag check across various parts of the codebase and -maintain the status of `default_enabled` in the YAML definition file which is the SSOT. - -If `default_enabled: :yaml` is used, a YAML definition is expected or an error is raised -in development or test environment, while returning `false` on production. - -If not specified, the default feature flag type for `Feature.enabled?` and `Feature.disabled?` -is `type: development`. For all other feature flag types, you must specify the `type:`: - -```ruby -if Feature.enabled?(:feature_flag, project, type: :ops) - # execute code if ops feature flag is enabled -else - # execute code if ops feature flag is disabled -end - -if Feature.disabled?(:my_feature_flag, project, type: :ops) - # execute code if feature flag is disabled -end -``` - -WARNING: -Don't use feature flags at application load time. For example, using the `Feature` class in -`config/initializers/*` or at the class level could cause an unexpected error. This error occurs -because a database that a feature flag adapter might depend on doesn't exist at load time -(especially for fresh installations). Checking for the database's existence at the caller isn't -recommended, as some adapters don't require a database at all (for example, the HTTP adapter). The -feature flag setup check must be abstracted in the `Feature` namespace. This approach also requires -application reload when the feature flag changes. You must therefore ask SREs to reload the -Web/API/Sidekiq fleet on production, which takes time to fully rollout/rollback the changes. For -these reasons, use environment variables (for example, `ENV['YOUR_FEATURE_NAME']`) or `gitlab.yml` -instead. - -Here's an example of a pattern that you should avoid: - -```ruby -class MyClass - if Feature.enabled?(:...) - new_process - else - legacy_process - end -end -``` - -### Frontend - -Use the `push_frontend_feature_flag` method for frontend code, which is -available to all controllers that inherit from `ApplicationController`. You can use -this method to expose the state of a feature flag, for example: - -```ruby -before_action do - # Prefer to scope it per project or user e.g. - push_frontend_feature_flag(:vim_bindings, project) -end - -def index - # ... -end - -def edit - # ... -end -``` - -You can then check the state of the feature flag in JavaScript as follows: - -```javascript -if ( gon.features.vimBindings ) { - // ... -} -``` - -The name of the feature flag in JavaScript is always camelCase, -so checking for `gon.features.vim_bindings` would not work. - -See the [Vue guide](../fe_guide/vue.md#accessing-feature-flags) for details about -how to access feature flags in a Vue component. - -In rare cases you may want to make a feature enabled by default. If so, explain the reasoning -in the merge request. Use `default_enabled: true` when checking the feature flag state: - -```ruby -before_action do - # Prefer to scope it per project or user e.g. - push_frontend_feature_flag(:vim_bindings, project, default_enabled: true) -end -``` - -If not specified, the default feature flag type for `push_frontend_feature_flag` -is `type: development`. For all other feature flag types, you must specify the `type:`: - -```ruby -before_action do - push_frontend_feature_flag(:vim_bindings, project, type: :ops) -end -``` - -### Feature actors - -**It is strongly advised to use actors with feature flags.** Actors provide a simple -way to enable a feature flag only for a given project, group or user. This makes debugging -easier, as you can filter logs and errors for example, based on actors. This also makes it possible -to enable the feature on the `gitlab-org` or `gitlab-com` groups first, while the rest of -the users aren't impacted. - -Actors also provide an easy way to do a percentage rollout of a feature in a sticky way. -If a 1% rollout enabled a feature for a specific actor, that actor will continue to have the feature enabled at -10%, 50%, and 100%. - -GitLab currently supports the following models as feature flag actors: - -- `User` -- `Project` -- `Group` - -The actor is a second parameter of the `Feature.enabled?` call. The -same actor type must be used consistently for all invocations of `Feature.enabled?`. - -```ruby -Feature.enabled?(:feature_flag, project) -Feature.enabled?(:feature_flag, group) -Feature.enabled?(:feature_flag, user) -``` - -#### Selectively disable by actor - -By default you cannot selectively disable a feature flag by actor. - -```shell -# This will not work how you would expect. -/chatops run feature set some_feature true -/chatops run feature set --project=gitlab-org/gitlab some_feature false -``` - -However, if you add two feature flags, you can write your conditional statement in such a way that the equivalent selective disable is possible. - -```ruby -Feature.enabled?(:a_feature, project) && Feature.disabled?(:a_feature_override, project) -``` - -```shell -# This will enable a feature flag globally, except for gitlab-org/gitlab -/chatops run feature set a_feature true -/chatops run feature set --project=gitlab-org/gitlab a_feature_override true -``` - -### Enable additional objects as actors - -To use feature gates based on actors, the model needs to respond to -`flipper_id`. For example, to enable for the Foo model: - -```ruby -class Foo < ActiveRecord::Base - include FeatureGate -end -``` - -Only models that `include FeatureGate` or expose `flipper_id` method can be -used as an actor for `Feature.enabled?`. - -### Feature flags for licensed features - -You can't use a feature flag with the same name as a licensed feature name, because -it would cause a naming collision. This was [widely discussed and removed](https://gitlab.com/gitlab-org/gitlab/-/issues/259611) -because it is confusing. - -To check for licensed features, add a dedicated feature flag under a different name -and check it explicitly, for example: - -```ruby -Feature.enabled?(:licensed_feature_feature_flag, project) && - project.feature_available?(:licensed_feature) -``` - -### Feature groups - -Feature groups must be defined statically in `lib/feature.rb` (in the -`.register_feature_groups` method), but their implementation can obviously be -dynamic (querying the DB, for example). - -Once defined in `lib/feature.rb`, you can to activate a -feature for a given feature group via the [`feature_group` parameter of the features API](../../api/features.md#set-or-create-a-feature) - -### Enabling a feature flag locally (in development) - -In the rails console (`rails c`), enter the following command to enable a feature flag: - -```ruby -Feature.enable(:feature_flag_name) -``` - -Similarly, the following command disables a feature flag: - -```ruby -Feature.disable(:feature_flag_name) -``` - -You can also enable a feature flag for a given gate: - -```ruby -Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project")) -``` - -### Removing a feature flag locally (in development) - -When manually enabling or disabling a feature flag from the Rails console, its default value gets overwritten. -This can cause confusion when changing the flag's `default_enabled` attribute. - -To reset the feature flag to the default status, you can remove it in the rails console (`rails c`) -as follows: - -```ruby -Feature.remove(:feature_flag_name) -``` - -## Feature flags in tests - -Introducing a feature flag into the codebase creates an additional code path that should be tested. -It is strongly advised to test all code affected by a feature flag, both when **enabled** and **disabled** -to ensure the feature works properly. - -When using the testing environment, all feature flags are enabled by default. - -WARNING: -This does not apply to end-to-end (QA) tests, which [do not disable feature flags by default](#end-to-end-qa-tests). There is a different [process for using feature flags in end-to-end tests](../testing_guide/end_to_end/feature_flags.md). - -To disable a feature flag in a test, use the `stub_feature_flags` -helper. For example, to globally disable the `ci_live_trace` feature -flag in a test: - -```ruby -stub_feature_flags(ci_live_trace: false) - -Feature.enabled?(:ci_live_trace) # => false -``` - -If you wish to set up a test where a feature flag is enabled only -for some actors and not others, you can specify this in options -passed to the helper. For example, to enable the `ci_live_trace` -feature flag for a specific project: - -```ruby -project1, project2 = build_list(:project, 2) - -# Feature will only be enabled for project1 -stub_feature_flags(ci_live_trace: project1) - -Feature.enabled?(:ci_live_trace) # => false -Feature.enabled?(:ci_live_trace, project1) # => true -Feature.enabled?(:ci_live_trace, project2) # => false -``` - -The behavior of FlipperGate is as follows: - -1. You can enable an override for a specified actor to be enabled. -1. You can disable (remove) an override for a specified actor, - falling back to the default state. -1. There's no way to model that you explicitly disabled a specified actor. - -```ruby -Feature.enable(:my_feature) -Feature.disable(:my_feature, project1) -Feature.enabled?(:my_feature) # => true -Feature.enabled?(:my_feature, project1) # => true - -Feature.disable(:my_feature2) -Feature.enable(:my_feature2, project1) -Feature.enabled?(:my_feature2) # => false -Feature.enabled?(:my_feature2, project1) # => true -``` - -### `have_pushed_frontend_feature_flags` - -Use `have_pushed_frontend_feature_flags` to test if [`push_frontend_feature_flag`](#frontend) -has added the feature flag to the HTML. - -For example, - -```ruby -stub_feature_flags(value_stream_analytics_path_navigation: false) - -visit group_analytics_cycle_analytics_path(group) - -expect(page).to have_pushed_frontend_feature_flags(valueStreamAnalyticsPathNavigation: false) -``` - -### `stub_feature_flags` vs `Feature.enable*` - -It is preferred to use `stub_feature_flags` to enable feature flags -in the testing environment. This method provides a simple and well described -interface for simple use cases. - -However, in some cases more complex behavior needs to be tested, -like percentage rollouts of feature flags. This can be done using -`.enable_percentage_of_time` or `.enable_percentage_of_actors`: - -```ruby -# Good: feature needs to be explicitly disabled, as it is enabled by default if not defined -stub_feature_flags(my_feature: false) -stub_feature_flags(my_feature: true) -stub_feature_flags(my_feature: project) -stub_feature_flags(my_feature: [project, project2]) - -# Bad -Feature.enable(:my_feature_2) - -# Good: enable my_feature for 50% of time -Feature.enable_percentage_of_time(:my_feature_3, 50) - -# Good: enable my_feature for 50% of actors/gates/things -Feature.enable_percentage_of_actors(:my_feature_4, 50) -``` - -Each feature flag that has a defined state is persisted -during test execution time: - -```ruby -Feature.persisted_names.include?('my_feature') => true -Feature.persisted_names.include?('my_feature_2') => true -Feature.persisted_names.include?('my_feature_3') => true -Feature.persisted_names.include?('my_feature_4') => true -``` - -### Stubbing actor - -When you want to enable a feature flag for a specific actor only, -you can stub its representation. A gate that is passed -as an argument to `Feature.enabled?` and `Feature.disabled?` must be an object -that includes `FeatureGate`. - -In specs you can use the `stub_feature_flag_gate` method that allows you to -quickly create a custom actor: - -```ruby -gate = stub_feature_flag_gate('CustomActor') - -stub_feature_flags(ci_live_trace: gate) - -Feature.enabled?(:ci_live_trace) # => false -Feature.enabled?(:ci_live_trace, gate) # => true -``` - -You can also disable a feature flag for a specific actor: - -```ruby -gate = stub_feature_flag_gate('CustomActor') - -stub_feature_flags(ci_live_trace: false, thing: gate) -``` - -### Controlling feature flags engine in tests - -Our Flipper engine in the test environment works in a memory mode `Flipper::Adapters::Memory`. -`production` and `development` modes use `Flipper::Adapters::ActiveRecord`. - -You can control whether the `Flipper::Adapters::Memory` or `ActiveRecord` mode is being used. - -#### `stub_feature_flags: true` (default and preferred) - -In this mode Flipper is configured to use `Flipper::Adapters::Memory` and mark all feature -flags to be on-by-default and persisted on a first use. This overwrites the `default_enabled:` -of `Feature.enabled?` and `Feature.disabled?` returning always `true` unless feature flag -is persisted. - -Make sure behavior under feature flag doesn't go untested in some non-specific contexts. - -### `stub_feature_flags: false` - -This disables a memory-stubbed flipper, and uses `Flipper::Adapters::ActiveRecord` -a mode that is used by `production` and `development`. - -You should use this mode only when you really want to tests aspects of Flipper -with how it interacts with `ActiveRecord`. - -### End-to-end (QA) tests - -Toggling feature flags works differently in end-to-end (QA) tests. The end-to-end test framework does not have direct access to -Rails or the database, so it can't use Flipper. Instead, it uses [the public API](../../api/features.md#set-or-create-a-feature). Each end-to-end test can [enable or disable a feature flag during the test](../testing_guide/end_to_end/feature_flags.md). Alternatively, you can enable or disable a feature flag before one or more tests when you [run them from your GitLab repository's `qa` directory](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled-or-disabled), or if you [run the tests via GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#running-tests-with-a-feature-flag-enabled). - -[As noted above, feature flags are not enabled by default in end-to-end tests.](#feature-flags-in-tests) -This means that end-to-end tests will run with feature flags in the default state implemented in the source -code, or with the feature flag in its current state on the GitLab instance under test, unless the -test is written to enable/disable a feature flag explicitly. - -When a feature flag is changed on Staging or on GitLab.com, a Slack message will be posted to the `#qa-staging` or `#qa-production` channels to inform -the pipeline triage DRI so that they can more easily determine if any failures are related to a feature flag change. However, if you are working on a change you can -help to avoid unexpected failures by [confirming that the end-to-end tests pass with a feature flag enabled.](../testing_guide/end_to_end/feature_flags.md#confirming-that-end-to-end-tests-pass-with-a-feature-flag-enabled) +This document was moved to [another location](index.md). +<!-- This redirect file can be deleted after 2021-06-01. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
\ No newline at end of file diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md index 4890cc5da35..5c98dc2e473 100644 --- a/doc/development/feature_flags/index.md +++ b/doc/development/feature_flags/index.md @@ -1,75 +1,636 @@ --- +type: reference, dev stage: none group: Development info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines" --- -# Feature flags in development of GitLab +# Developing with feature flags **NOTE**: The documentation below covers feature flags used by GitLab to deploy its own features, which **is not** the same as the [feature flags offered as part of the product](../../operations/feature_flags.md). -## When to use feature flags +This document provides guidelines on how to use feature flags +in the GitLab codebase to conditionally enable features +and test them. -Developers are required to use feature flags for changes that could affect availability of existing GitLab functionality (if it only affects the new feature you're making that is probably acceptable). -Such changes include: +Features that are developed and merged behind a feature flag +should not include a changelog entry. The entry should be added either in the merge +request removing the feature flag or the merge request where the default value of +the feature flag is set to enabled. If the feature contains any database migrations, it +*should* include a changelog entry for the database changes. -1. New features in high traffic areas (e.g. a new merge request widget, new option in issues/epics, new CI functionality). -1. Complex performance improvements that may require additional testing in production (e.g. rewriting complex queries, changes to frequently used API endpoints). -1. Invasive changes to the user interface (e.g. introducing a new navigation bar, removal of a sidebar, UI element change in issues or MR interface). -1. Introducing dependencies on third-party services (e.g. adding support for importing projects). -1. Changes to features that can cause data corruption or cause data loss (e.g. features processing repository data or user uploaded content). +WARNING: +All newly-introduced feature flags should be [disabled by default](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#feature-flags-in-gitlab-development). -Situations where you might consider not using a feature flag: +NOTE: +This document is the subject of continued work as part of an epic to [improve internal usage of Feature Flags](https://gitlab.com/groups/gitlab-org/-/epics/3551). Raise any suggestions as new issues and attach them to the epic. -1. Adding a new API endpoint -1. Introducing new features in low traffic areas (e.g. adding a new export functionality in the admin area/group settings/project settings) -1. Non-invasive frontend changes (e.g. changing the color of a button, or moving a UI element in a low traffic area) +## Feature flags in GitLab development -In all cases, those working on the changes should ask themselves: +The following highlights should be considered when deciding if feature flags +should be leveraged: -> Why do I need to add a feature flag? If I don't add one, what options do I have to control the impact on application reliability, and user experience? +- By default, the feature flags should be **off**. +- Feature flags should remain in the codebase for as short period as possible + to reduce the need for feature flag accounting. +- The person operating with feature flags is responsible for clearly communicating + the status of a feature behind the feature flag with responsible stakeholders. The + issue description should be updated with the feature flag name and whether it is + defaulted on or off as soon it is evident that a feature flag is needed. +- Merge requests that make changes hidden behind a feature flag, or remove an + existing feature flag because a feature is deemed stable must have the + ~"feature flag" label assigned. +- When development of a feature will be spread across multiple merge + requests, you can use the following workflow: -For perspective on why we limit our use of feature flags please see -<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Feature flags only when needed](https://www.youtube.com/watch?v=DQaGqyolOd8). + 1. [Create a new feature flag](#create-a-new-feature-flag) + which is **off** by default, in the first merge request which uses the flag. + Flags [should not be added separately](#risk-of-a-broken-master-main-branch). + 1. Submit incremental changes via one or more merge requests, ensuring that any + new code added can only be reached if the feature flag is **on**. + You can keep the feature flag enabled on your local GDK during development. + 1. When the feature is ready to be tested, enable the feature flag for + a specific project and ensure that there are no issues with the implementation. + 1. When the feature is ready to be announced, create a merge request that adds + documentation about the feature, including [documentation for the feature flag itself](../documentation/feature_flags.md), + and a changelog entry. In the same merge request either flip the feature flag to + be **on by default** or remove it entirely in order to enable the new behavior. -In case you are uncertain if a feature flag is necessary, simply ask about this in an early merge request, and those reviewing the changes will likely provide you with an answer. +One might be tempted to think that feature flags will delay the release of a +feature by at least one month (= one release). This is not the case. A feature +flag does not have to stick around for a specific amount of time +(e.g. at least one release), instead they should stick around until the feature +is deemed stable. Stable means it works on GitLab.com without causing any +problems, such as outages. -When using a feature flag for UI elements, make sure to _also_ use a feature -flag for the underlying backend code, if there is any. This ensures there is -absolutely no way to use the feature until it is enabled. +## Risk of a broken master (main) branch -## How to use Feature Flags +Feature flags **must** be used in the MR that introduces them. Not doing so causes a +[broken master](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) scenario due +to the `rspec:feature-flags` job that only runs on the `master` branch. -Feature flags can be used to gradually deploy changes, regardless of whether -they are new features or performance improvements. By using feature flags, -you can determine the impact of GitLab-directed changes, while still being able -to disable those changes without having to revert an entire release. +## Types of feature flags -For an overview about starting with feature flags in GitLab development, -use this [training template](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/.gitlab/issue_templates/feature-flag-training.md). +Choose a feature flag type that matches the expected usage. -Before using feature flags for GitLab development, review the following development guides: +### `development` type -1. [Process for using features flags](process.md): When you should use - feature flags in the development of GitLab, what's the cost of using them, - and how to include them in a release. -1. [Developing with feature flags](development.md): Learn about the types of - feature flags, their definition and validation, how to create them, frontend and - backend details, and other information. -1. [Documenting features deployed behind feature flags](../documentation/feature_flags.md): - How to document features deployed behind feature flags, and how to update the - documentation for features' flags when their states change. -1. [Controlling feature flags](controls.md): Learn the process for deploying - a new feature, enabling it on GitLab.com, communicating the change, - logging, and cleaning up. +`development` feature flags are short-lived feature flags, +used so that unfinished code can be deployed in production. -User guides: +A `development` feature flag should have a rollout issue, +ideally created using the [Feature Flag Roll Out template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md). -1. [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.md): - An explanation for GitLab administrators about how they can - enable or disable GitLab features behind feature flags. -1. [What "features deployed behind flags" means to the GitLab user](../../user/feature_flags.md): - An explanation for GitLab users regarding how certain features - might not be available to them until they are enabled. +This is the default type used when calling `Feature.enabled?`. + +### `ops` type + +`ops` feature flags are long-lived feature flags that control operational aspects +of GitLab product behavior. For example, feature flags that disable features that might +have a performance impact, like special Sidekiq worker behavior. + +`ops` feature flags likely do not have rollout issues, as it is hard to +predict when they are enabled or disabled. + +To use `ops` feature flags, you must append `type: :ops` to `Feature.enabled?` +invocations: + +```ruby +# Check if feature flag is enabled +Feature.enabled?(:my_ops_flag, project, type: :ops) + +# Check if feature flag is disabled +Feature.disabled?(:my_ops_flag, project, type: :ops) + +# Push feature flag to Frontend +push_frontend_feature_flag(:my_ops_flag, project, type: :ops) +``` + +### `experiment` type + +`experiment` feature flags are used for A/B testing on GitLab.com. + +An `experiment` feature flag should conform to the same standards as a `development` feature flag, +although the interface has some differences. An experiment feature flag should have a rollout issue, +ideally created using the [Experiment Tracking template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/experiment_tracking_template.md). More information can be found in the [experiment guide](../experiment_guide/index.md). + +## Feature flag definition and validation + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229161) in GitLab 13.3. + +During development (`RAILS_ENV=development`) or testing (`RAILS_ENV=test`) all feature flag usage is being strictly validated. + +This process is meant to ensure consistent feature flag usage in the codebase. All feature flags **must**: + +- Be known. Only use feature flags that are explicitly defined. +- Not be defined twice. They have to be defined either in FOSS or EE, but not both. +- Use a valid and consistent `type:` across all invocations. +- Use the same `default_enabled:` across all invocations. +- Have an owner. + +All feature flags known to GitLab are self-documented in YAML files stored in: + +- [`config/feature_flags`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/feature_flags) +- [`ee/config/feature_flags`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/config/feature_flags) + +Each feature flag is defined in a separate YAML file consisting of a number of fields: + +| Field | Required | Description | +|---------------------|----------|----------------------------------------------------------------| +| `name` | yes | Name of the feature flag. | +| `type` | yes | Type of feature flag. | +| `default_enabled` | yes | The default state of the feature flag that is strictly validated, with `default_enabled:` passed as an argument. | +| `introduced_by_url` | no | The URL to the Merge Request that introduced the feature flag. | +| `rollout_issue_url` | no | The URL to the Issue covering the feature flag rollout. | +| `group` | no | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the feature flag. | + +NOTE: +All validations are skipped when running in `RAILS_ENV=production`. + +## Create a new feature flag + +The GitLab codebase provides [`bin/feature-flag`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/bin/feature-flag), +a dedicated tool to create new feature flag definitions. +The tool asks various questions about the new feature flag, then creates +a YAML definition in `config/feature_flags` or `ee/config/feature_flags`. + +Only feature flags that have a YAML definition file can be used when running the development or testing environments. + +```shell +$ bin/feature-flag my_feature_flag +>> Specify the group introducing the feature flag, like `group::apm`: +?> group::memory + +>> URL of the MR introducing the feature flag (enter to skip): +?> https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38602 + +>> Open this URL and fill in the rest of the details: +https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue%5Btitle%5D=%5BFeature+flag%5D+Rollout+of+%60test-flag%60&issuable_template=Feature+Flag+Roll+Out + +>> URL of the rollout issue (enter to skip): +?> https://gitlab.com/gitlab-org/gitlab/-/issues/232533 +create config/feature_flags/development/my_feature_flag.yml +--- +name: my_feature_flag +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38602 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232533 +group: group::memory +type: development +default_enabled: false +``` + +NOTE: +To create a feature flag that is only used in EE, add the `--ee` flag: `bin/feature-flag --ee` + +## Delete a feature flag + +See [cleaning up feature flags](controls.md#cleaning-up) for more information about +deleting feature flags. + +## Develop with a feature flag + +There are two main ways of using Feature Flags in the GitLab codebase: + +- [Backend code (Rails)](#backend) +- [Frontend code (VueJS)](#frontend) + +### Backend + +The feature flag interface is defined in [`lib/feature.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/feature.rb). +This interface provides a set of methods to check if the feature flag is enabled or disabled: + +```ruby +if Feature.enabled?(:my_feature_flag, project) + # execute code if feature flag is enabled +else + # execute code if feature flag is disabled +end + +if Feature.disabled?(:my_feature_flag, project) + # execute code if feature flag is disabled +end +``` + +In rare cases you may want to make a feature enabled by default. If so, explain the reasoning +in the merge request. Use `default_enabled: true` when checking the feature flag state: + +```ruby +if Feature.enabled?(:feature_flag, project, default_enabled: true) + # execute code if feature flag is enabled +else + # execute code if feature flag is disabled +end + +if Feature.disabled?(:my_feature_flag, project, default_enabled: true) + # execute code if feature flag is disabled +end +``` + +If not specified, `default_enabled` is `false`. + +To force reading the `default_enabled` value from the relative YAML definition file, use +`default_enabled: :yaml`: + +```ruby +if Feature.enabled?(:feature_flag, project, default_enabled: :yaml) + # execute code if feature flag is enabled +end +``` + +```ruby +if Feature.disabled?(:feature_flag, project, default_enabled: :yaml) + # execute code if feature flag is disabled +end +``` + +This allows to use the same feature flag check across various parts of the codebase and +maintain the status of `default_enabled` in the YAML definition file which is the SSOT. + +If `default_enabled: :yaml` is used, a YAML definition is expected or an error is raised +in development or test environment, while returning `false` on production. + +If not specified, the default feature flag type for `Feature.enabled?` and `Feature.disabled?` +is `type: development`. For all other feature flag types, you must specify the `type:`: + +```ruby +if Feature.enabled?(:feature_flag, project, type: :ops) + # execute code if ops feature flag is enabled +else + # execute code if ops feature flag is disabled +end + +if Feature.disabled?(:my_feature_flag, project, type: :ops) + # execute code if feature flag is disabled +end +``` + +WARNING: +Don't use feature flags at application load time. For example, using the `Feature` class in +`config/initializers/*` or at the class level could cause an unexpected error. This error occurs +because a database that a feature flag adapter might depend on doesn't exist at load time +(especially for fresh installations). Checking for the database's existence at the caller isn't +recommended, as some adapters don't require a database at all (for example, the HTTP adapter). The +feature flag setup check must be abstracted in the `Feature` namespace. This approach also requires +application reload when the feature flag changes. You must therefore ask SREs to reload the +Web/API/Sidekiq fleet on production, which takes time to fully rollout/rollback the changes. For +these reasons, use environment variables (for example, `ENV['YOUR_FEATURE_NAME']`) or `gitlab.yml` +instead. + +Here's an example of a pattern that you should avoid: + +```ruby +class MyClass + if Feature.enabled?(:...) + new_process + else + legacy_process + end +end +``` + +### Frontend + +Use the `push_frontend_feature_flag` method for frontend code, which is +available to all controllers that inherit from `ApplicationController`. You can use +this method to expose the state of a feature flag, for example: + +```ruby +before_action do + # Prefer to scope it per project or user e.g. + push_frontend_feature_flag(:vim_bindings, project) +end + +def index + # ... +end + +def edit + # ... +end +``` + +You can then check the state of the feature flag in JavaScript as follows: + +```javascript +if ( gon.features.vimBindings ) { + // ... +} +``` + +The name of the feature flag in JavaScript is always camelCase, +so checking for `gon.features.vim_bindings` would not work. + +See the [Vue guide](../fe_guide/vue.md#accessing-feature-flags) for details about +how to access feature flags in a Vue component. + +In rare cases you may want to make a feature enabled by default. If so, explain the reasoning +in the merge request. Use `default_enabled: true` when checking the feature flag state: + +```ruby +before_action do + # Prefer to scope it per project or user e.g. + push_frontend_feature_flag(:vim_bindings, project, default_enabled: true) +end +``` + +If not specified, the default feature flag type for `push_frontend_feature_flag` +is `type: development`. For all other feature flag types, you must specify the `type:`: + +```ruby +before_action do + push_frontend_feature_flag(:vim_bindings, project, type: :ops) +end +``` + +### Feature actors + +**It is strongly advised to use actors with feature flags.** Actors provide a simple +way to enable a feature flag only for a given project, group or user. This makes debugging +easier, as you can filter logs and errors for example, based on actors. This also makes it possible +to enable the feature on the `gitlab-org` or `gitlab-com` groups first, while the rest of +the users aren't impacted. + +Actors also provide an easy way to do a percentage rollout of a feature in a sticky way. +If a 1% rollout enabled a feature for a specific actor, that actor will continue to have the feature enabled at +10%, 50%, and 100%. + +GitLab currently supports the following models as feature flag actors: + +- `User` +- `Project` +- `Group` + +The actor is a second parameter of the `Feature.enabled?` call. The +same actor type must be used consistently for all invocations of `Feature.enabled?`. + +```ruby +Feature.enabled?(:feature_flag, project) +Feature.enabled?(:feature_flag, group) +Feature.enabled?(:feature_flag, user) +``` + +#### Selectively disable by actor + +By default you cannot selectively disable a feature flag by actor. + +```shell +# This will not work how you would expect. +/chatops run feature set some_feature true +/chatops run feature set --project=gitlab-org/gitlab some_feature false +``` + +However, if you add two feature flags, you can write your conditional statement in such a way that the equivalent selective disable is possible. + +```ruby +Feature.enabled?(:a_feature, project) && Feature.disabled?(:a_feature_override, project) +``` + +```shell +# This will enable a feature flag globally, except for gitlab-org/gitlab +/chatops run feature set a_feature true +/chatops run feature set --project=gitlab-org/gitlab a_feature_override true +``` + +### Enable additional objects as actors + +To use feature gates based on actors, the model needs to respond to +`flipper_id`. For example, to enable for the Foo model: + +```ruby +class Foo < ActiveRecord::Base + include FeatureGate +end +``` + +Only models that `include FeatureGate` or expose `flipper_id` method can be +used as an actor for `Feature.enabled?`. + +### Feature flags for licensed features + +You can't use a feature flag with the same name as a licensed feature name, because +it would cause a naming collision. This was [widely discussed and removed](https://gitlab.com/gitlab-org/gitlab/-/issues/259611) +because it is confusing. + +To check for licensed features, add a dedicated feature flag under a different name +and check it explicitly, for example: + +```ruby +Feature.enabled?(:licensed_feature_feature_flag, project) && + project.feature_available?(:licensed_feature) +``` + +### Feature groups + +Feature groups must be defined statically in `lib/feature.rb` (in the +`.register_feature_groups` method), but their implementation can obviously be +dynamic (querying the DB, for example). + +Once defined in `lib/feature.rb`, you can to activate a +feature for a given feature group via the [`feature_group` parameter of the features API](../../api/features.md#set-or-create-a-feature) + +### Enabling a feature flag locally (in development) + +In the rails console (`rails c`), enter the following command to enable a feature flag: + +```ruby +Feature.enable(:feature_flag_name) +``` + +Similarly, the following command disables a feature flag: + +```ruby +Feature.disable(:feature_flag_name) +``` + +You can also enable a feature flag for a given gate: + +```ruby +Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project")) +``` + +### Removing a feature flag locally (in development) + +When manually enabling or disabling a feature flag from the Rails console, its default value gets overwritten. +This can cause confusion when changing the flag's `default_enabled` attribute. + +To reset the feature flag to the default status, you can remove it in the rails console (`rails c`) +as follows: + +```ruby +Feature.remove(:feature_flag_name) +``` + +## Feature flags in tests + +Introducing a feature flag into the codebase creates an additional code path that should be tested. +It is strongly advised to test all code affected by a feature flag, both when **enabled** and **disabled** +to ensure the feature works properly. + +When using the testing environment, all feature flags are enabled by default. + +WARNING: +This does not apply to end-to-end (QA) tests, which [do not disable feature flags by default](#end-to-end-qa-tests). There is a different [process for using feature flags in end-to-end tests](../testing_guide/end_to_end/feature_flags.md). + +To disable a feature flag in a test, use the `stub_feature_flags` +helper. For example, to globally disable the `ci_live_trace` feature +flag in a test: + +```ruby +stub_feature_flags(ci_live_trace: false) + +Feature.enabled?(:ci_live_trace) # => false +``` + +If you wish to set up a test where a feature flag is enabled only +for some actors and not others, you can specify this in options +passed to the helper. For example, to enable the `ci_live_trace` +feature flag for a specific project: + +```ruby +project1, project2 = build_list(:project, 2) + +# Feature will only be enabled for project1 +stub_feature_flags(ci_live_trace: project1) + +Feature.enabled?(:ci_live_trace) # => false +Feature.enabled?(:ci_live_trace, project1) # => true +Feature.enabled?(:ci_live_trace, project2) # => false +``` + +The behavior of FlipperGate is as follows: + +1. You can enable an override for a specified actor to be enabled. +1. You can disable (remove) an override for a specified actor, + falling back to the default state. +1. There's no way to model that you explicitly disabled a specified actor. + +```ruby +Feature.enable(:my_feature) +Feature.disable(:my_feature, project1) +Feature.enabled?(:my_feature) # => true +Feature.enabled?(:my_feature, project1) # => true + +Feature.disable(:my_feature2) +Feature.enable(:my_feature2, project1) +Feature.enabled?(:my_feature2) # => false +Feature.enabled?(:my_feature2, project1) # => true +``` + +### `have_pushed_frontend_feature_flags` + +Use `have_pushed_frontend_feature_flags` to test if [`push_frontend_feature_flag`](#frontend) +has added the feature flag to the HTML. + +For example, + +```ruby +stub_feature_flags(value_stream_analytics_path_navigation: false) + +visit group_analytics_cycle_analytics_path(group) + +expect(page).to have_pushed_frontend_feature_flags(valueStreamAnalyticsPathNavigation: false) +``` + +### `stub_feature_flags` vs `Feature.enable*` + +It is preferred to use `stub_feature_flags` to enable feature flags +in the testing environment. This method provides a simple and well described +interface for simple use cases. + +However, in some cases more complex behavior needs to be tested, +like percentage rollouts of feature flags. This can be done using +`.enable_percentage_of_time` or `.enable_percentage_of_actors`: + +```ruby +# Good: feature needs to be explicitly disabled, as it is enabled by default if not defined +stub_feature_flags(my_feature: false) +stub_feature_flags(my_feature: true) +stub_feature_flags(my_feature: project) +stub_feature_flags(my_feature: [project, project2]) + +# Bad +Feature.enable(:my_feature_2) + +# Good: enable my_feature for 50% of time +Feature.enable_percentage_of_time(:my_feature_3, 50) + +# Good: enable my_feature for 50% of actors/gates/things +Feature.enable_percentage_of_actors(:my_feature_4, 50) +``` + +Each feature flag that has a defined state is persisted +during test execution time: + +```ruby +Feature.persisted_names.include?('my_feature') => true +Feature.persisted_names.include?('my_feature_2') => true +Feature.persisted_names.include?('my_feature_3') => true +Feature.persisted_names.include?('my_feature_4') => true +``` + +### Stubbing actor + +When you want to enable a feature flag for a specific actor only, +you can stub its representation. A gate that is passed +as an argument to `Feature.enabled?` and `Feature.disabled?` must be an object +that includes `FeatureGate`. + +In specs you can use the `stub_feature_flag_gate` method that allows you to +quickly create a custom actor: + +```ruby +gate = stub_feature_flag_gate('CustomActor') + +stub_feature_flags(ci_live_trace: gate) + +Feature.enabled?(:ci_live_trace) # => false +Feature.enabled?(:ci_live_trace, gate) # => true +``` + +You can also disable a feature flag for a specific actor: + +```ruby +gate = stub_feature_flag_gate('CustomActor') + +stub_feature_flags(ci_live_trace: false, thing: gate) +``` + +### Controlling feature flags engine in tests + +Our Flipper engine in the test environment works in a memory mode `Flipper::Adapters::Memory`. +`production` and `development` modes use `Flipper::Adapters::ActiveRecord`. + +You can control whether the `Flipper::Adapters::Memory` or `ActiveRecord` mode is being used. + +#### `stub_feature_flags: true` (default and preferred) + +In this mode Flipper is configured to use `Flipper::Adapters::Memory` and mark all feature +flags to be on-by-default and persisted on a first use. This overwrites the `default_enabled:` +of `Feature.enabled?` and `Feature.disabled?` returning always `true` unless feature flag +is persisted. + +Make sure behavior under feature flag doesn't go untested in some non-specific contexts. + +### `stub_feature_flags: false` + +This disables a memory-stubbed flipper, and uses `Flipper::Adapters::ActiveRecord` +a mode that is used by `production` and `development`. + +You should use this mode only when you really want to tests aspects of Flipper +with how it interacts with `ActiveRecord`. + +### End-to-end (QA) tests + +Toggling feature flags works differently in end-to-end (QA) tests. The end-to-end test framework does not have direct access to +Rails or the database, so it can't use Flipper. Instead, it uses [the public API](../../api/features.md#set-or-create-a-feature). Each end-to-end test can [enable or disable a feature flag during the test](../testing_guide/end_to_end/feature_flags.md). Alternatively, you can enable or disable a feature flag before one or more tests when you [run them from your GitLab repository's `qa` directory](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled-or-disabled), or if you [run the tests via GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#running-tests-with-a-feature-flag-enabled). + +[As noted above, feature flags are not enabled by default in end-to-end tests.](#feature-flags-in-tests) +This means that end-to-end tests will run with feature flags in the default state implemented in the source +code, or with the feature flag in its current state on the GitLab instance under test, unless the +test is written to enable/disable a feature flag explicitly. + +When a feature flag is changed on Staging or on GitLab.com, a Slack message will be posted to the `#qa-staging` or `#qa-production` channels to inform +the pipeline triage DRI so that they can more easily determine if any failures are related to a feature flag change. However, if you are working on a change you can +help to avoid unexpected failures by [confirming that the end-to-end tests pass with a feature flag enabled.](../testing_guide/end_to_end/feature_flags.md#confirming-that-end-to-end-tests-pass-with-a-feature-flag-enabled) diff --git a/doc/development/feature_flags/process.md b/doc/development/feature_flags/process.md index 65a6d01e0a2..247dafe9f0b 100644 --- a/doc/development/feature_flags/process.md +++ b/doc/development/feature_flags/process.md @@ -1,177 +1,8 @@ --- -type: reference, dev -stage: none -group: Development -info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines" +redirect_to: 'https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/' --- -# Feature flags process +This document was moved to [another location](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/). -## Feature flags for user applications - -This document only covers feature flags used in the development of GitLab -itself. Feature flags in deployed user applications can be found at -[Feature Flags feature documentation](../../operations/feature_flags.md). - -## Feature flags in GitLab development - -The following highlights should be considered when deciding if feature flags -should be leveraged: - -- By default, the feature flags should be **off**. -- Feature flags should remain in the codebase for as short period as possible - to reduce the need for feature flag accounting. -- The person operating with feature flags is responsible for clearly communicating - the status of a feature behind the feature flag with responsible stakeholders. The - issue description should be updated with the feature flag name and whether it is - defaulted on or off as soon it is evident that a feature flag is needed. -- Merge requests that make changes hidden behind a feature flag, or remove an - existing feature flag because a feature is deemed stable must have the - ~"feature flag" label assigned. -- When development of a feature will be spread across multiple merge - requests, you can use the following workflow: - - 1. [Create a new feature flag](development.md#create-a-new-feature-flag) - which is **off** by default, in the first merge request which uses the flag. - Flags [should not be added separately](development.md#risk-of-a-broken-master-main-branch). - 1. Submit incremental changes via one or more merge requests, ensuring that any - new code added can only be reached if the feature flag is **on**. - You can keep the feature flag enabled on your local GDK during development. - 1. When the feature is ready to be tested, enable the feature flag for - a specific project and ensure that there are no issues with the implementation. - 1. When the feature is ready to be announced, create a merge request that adds - documentation about the feature, including [documentation for the feature flag itself](../documentation/feature_flags.md), - and a changelog entry. In the same merge request either flip the feature flag to - be **on by default** or remove it entirely in order to enable the new behavior. - -One might be tempted to think that feature flags will delay the release of a -feature by at least one month (= one release). This is not the case. A feature -flag does not have to stick around for a specific amount of time -(e.g. at least one release), instead they should stick around until the feature -is deemed stable. Stable means it works on GitLab.com without causing any -problems, such as outages. - -Please also read the [development guide for feature flags](development.md). - -### Including a feature behind feature flag in the final release - -In order to build a final release and present the feature for self-managed -users, the feature flag should be at least defaulted to **on**. If the feature -is deemed stable and there is confidence that removing the feature flag is safe, -consider removing the feature flag altogether. It's _strongly_ recommended that -the feature flag is [enabled **globally** on **production**](controls.md#enabling-a-feature-for-gitlabcom) for **at least one day** -before making this decision. Unexpected bugs are sometimes discovered during this period. - -The process for enabling features that are disabled by default can take 5-6 days -from when the merge request is first reviewed to when the change is deployed to -GitLab.com. However, it is recommended to allow 10-14 days for this activity to -account for unforeseen problems. - -Feature flags must be [documented according to their state (enabled/disabled)](../documentation/feature_flags.md), -and when the state changes, docs **must** be updated accordingly. - -NOTE: -Take into consideration that such action can make the feature available on -GitLab.com shortly after the change to the feature flag is merged. - -Changing the default state or removing the feature flag has to be done before -the 22nd of the month, _at least_ 3-4 working days before, in order for the change -to be included in the final self-managed release. - -In addition to this, the feature behind feature flag should: - -- Run in all GitLab.com environments for a sufficient period of time. This time - period depends on the feature behind the feature flag, but as a general rule of - thumb 2-4 working days should be sufficient to gather enough feedback. -- The feature should be exposed to all users within the GitLab.com plan during - the above mentioned period of time. Exposing the feature to a smaller percentage - or only a group of users might not expose a sufficient amount of information to aid in - making a decision on feature stability. - -While rare, release managers may decide to reject picking or revert a change in -a stable branch, even when feature flags are used. This might be necessary if -the changes are deemed problematic, too invasive, or there simply isn't enough -time to properly measure how the changes behave on GitLab.com. - -### The cost of feature flags - -When reading the above, one might be tempted to think this procedure is going to -add a lot of work. Fortunately, this is not the case, and we'll show why. For -this example we'll specify the cost of the work to do as a number, ranging from -0 to infinity. The greater the number, the more expensive the work is. The cost -does _not_ translate to time, it's just a way of measuring complexity of one -change relative to another. - -Let's say we are building a new feature, and we have determined that the cost of -this is 10. We have also determined that the cost of adding a feature flag check -in a variety of places is 1. If we do not use feature flags, and our feature -works as intended, our total cost is 10. This however is the best case scenario. -Optimizing for the best case scenario is guaranteed to lead to trouble, whereas -optimizing for the worst case scenario is almost always better. - -To illustrate this, let's say our feature causes an outage, and there's no -immediate way to resolve it. This means we'd have to take the following steps to -resolve the outage: - -1. Revert the release. -1. Perform any cleanups that might be necessary, depending on the changes that - were made. -1. Revert the commit, ensuring the "master" branch remains stable. This is - especially necessary if solving the problem can take days or even weeks. -1. Pick the revert commit into the appropriate stable branches, ensuring we - don't block any future releases until the problem is resolved. - -As history has shown, these steps are time consuming, complex, often involve -many developers, and worst of all: our users will have a bad experience using -GitLab.com until the problem is resolved. - -Now let's say that all of this has an associated cost of 10. This means that in -the worst case scenario, which we should optimize for, our total cost is now 20. - -If we had used a feature flag, things would have been very different. We don't -need to revert a release, and because feature flags are disabled by default we -don't need to revert and pick any Git commits. In fact, all we have to do is -disable the feature, and in the worst case, perform cleanup. Let's say that -the cost of this is 2. In this case, our best case cost is 11: 10 to build the -feature, and 1 to add the feature flag. The worst case cost is now 13: - -- 10 to build the feature. -- 1 to add the feature flag. -- 2 to disable and clean up. - -Here we can see that in the best case scenario the work necessary is only a tiny -bit more compared to not using a feature flag. Meanwhile, the process of -reverting our changes has been made significantly and reliably cheaper. - -In other words, feature flags do not slow down the development process. Instead, -they speed up the process as managing incidents now becomes _much_ easier. Once -continuous deployments are easier to perform, the time to iterate on a feature -is reduced even further, as you no longer need to wait weeks before your changes -are available on GitLab.com. - -### The benefits of feature flags - -It may seem like feature flags are configuration, which goes against our [convention-over-configuration](https://about.gitlab.com/handbook/product/product-principles/#convention-over-configuration) -principle. However, configuration is by definition something that is user-manageable. -Feature flags are not intended to be user-editable. Instead, they are intended as a tool for Engineers -and Site Reliability Engineers to use to de-risk their changes. Feature flags are the shim that gets us -to Continuous Delivery with our monorepo and without having to deploy the entire codebase on every change. -Feature flags are created to ensure that we can safely rollout our work on our terms. -If we use Feature Flags as a configuration, we are doing it wrong and are indeed in violation of our -principles. If something needs to be configured, we should intentionally make it configuration from the -first moment. - -Some of the benefits of using development-type feature flags are: - -1. It enables Continuous Delivery for GitLab.com. -1. It significantly reduces Mean-Time-To-Recovery. -1. It helps engineers to monitor and reduce the impact of their changes gradually, at any scale, - allowing us to be more metrics-driven and execute good DevOps practices, [shifting some responsibility "left"](https://devops.com/why-its-time-for-site-reliability-engineering-to-shift-left/). -1. Controlled feature rollout timing: without feature flags, we would need to wait until a specific - deployment was complete (which at GitLab could be at any time). -1. Increased psychological safety: when a feature flag is used, an engineer has the confidence that if anything goes wrong they can quickly disable the code and minimize the impact of a change that might be risky. -1. Improved throughput: when a change is less risky because a flag exists, theoretical tests about - scalability can potentially become unnecessary or less important. This allows an engineer to - potentially test a feature on a small project, monitor the impact, and proceed. The alternative might - be to build complex benchmarks locally, or on staging, or on another GitLab deployment, which has a - large impact on the time it can take to build and release a feature. +<!-- This redirect file can be deleted after 2021-06-01. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
\ No newline at end of file diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md index 08adb7faeb2..36b9064bbc4 100644 --- a/doc/development/features_inside_dot_gitlab.md +++ b/doc/development/features_inside_dot_gitlab.md @@ -10,8 +10,8 @@ We have implemented standard features that depend on configuration files in the When implementing new features, please refer to these existing features to avoid conflicts: - [Custom Dashboards](../operations/metrics/dashboards/index.md#add-a-new-dashboard-to-your-project): `.gitlab/dashboards/`. -- [Issue Templates](../user/project/description_templates.md#creating-issue-templates): `.gitlab/issue_templates/`. -- [Merge Request Templates](../user/project/description_templates.md#creating-merge-request-templates): `.gitlab/merge_request_templates/`. +- [Issue Templates](../user/project/description_templates.md#create-an-issue-template): `.gitlab/issue_templates/`. +- [Merge Request Templates](../user/project/description_templates.md#create-a-merge-request-template): `.gitlab/merge_request_templates/`. - [GitLab Kubernetes Agents](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/configuration_repository.md#layout): `.gitlab/agents/`. - [CODEOWNERS](../user/project/code_owners.md#how-to-set-up-code-owners): `.gitlab/CODEOWNERS`. - [Route Maps](../ci/review_apps/#route-maps): `.gitlab/route-map.yml`. diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md index 0be772db12e..f50e19bc383 100644 --- a/doc/development/gemfile.md +++ b/doc/development/gemfile.md @@ -31,3 +31,58 @@ You should also update npm packages that follow the current version of Rails: - `@rails/ujs` - `@rails/actioncable` + +## Upgrading dependencies because of vulnerabilities + +When upgrading dependencies because of a vulnerability, we +should pin the minimal version of the gem in which the vulnerability +was fixed in our Gemfile to avoid accidentally downgrading. + +For example, consider that the gem `license_finder` has `thor` as its +dependency. `thor` was found vulnerable until its version `1.1.1`, +which includes the vulnerability fix. + +In the Gemfile, make sure to pin `thor` to `1.1.1`. The direct +dependency `license_finder` should already have the version specified. + +```ruby +gem 'license_finder', '~> 6.0' +# Dependency of license_finder with fix for vulnerability +# _link to initial security issue that will become public in time_ +gem 'thor', '>= 1.1.1' +``` + +Here we're using the operator `>=` (greater than or equal to) rather +than `~>` ([pessimistic +operator](https://thoughtbot.com/blog/rubys-pessimistic-operator)) +making it possible to upgrade `license_finder` or any other gem to a +version that depends on `thor 1.2`. + +Simlarly, if `license_finder` had a vulnerability fixed in 6.0.1, we +should add: + +```ruby +gem 'license_finder', '~> 6.0', '>= 6.0.1' +``` + +This way, other dependencies rather than `license_finder` can +still depend on a newer version of `thor`, such as `6.0.2`, but would +not be able to depend on the vulnerable version `6.0.0`. + +A downgrade like that could happen if we introduced a new dependency +that also relied on thor but had its version pinned to a vulnerable +one. These changes are easy to miss in the `Gemfile.lock`. Pinning the +version would result in a conflict that would need to be solved. + +To avoid upgrading indirect dependencies, we can use [`bundle update +--conservative`](https://bundler.io/man/bundle-update.1.html#OPTIONS). + +When submitting a merge request including a dependency update, +include a link to the Gem diff between the 2 versions in the merge request +description. You can find this link on `rubygems.org` under +**Review Changes**. When you click it, RubyGems generates a comparison +between the versions on `diffend.io`. For example, this is the gem +diff for [`thor` 1.0.0 vs +1.0.1](https://my.diffend.io/gems/thor/1.0.0/1.0.1). Use the +links directly generated from RubyGems, since the links from GitLab or other code-hosting +platforms might not reflect the code that's actually published. diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md index e615fbc87a9..055b9ce4ad6 100644 --- a/doc/development/geo/framework.md +++ b/doc/development/geo/framework.md @@ -289,7 +289,7 @@ For example, to add support for files referenced by a `Widget` model with a t.binary :verification_checksum t.binary :verification_checksum_mismatched t.string :verification_failure, limit: 255 - t.text :last_sync_failure + t.string :last_sync_failure, limit: 255 t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true t.index :retry_at @@ -303,8 +303,6 @@ For example, to add support for files referenced by a `Widget` model with a end end end - - add_text_limit :widget_registry, :last_sync_failure, 255 end def down @@ -319,10 +317,7 @@ For example, to add support for files referenced by a `Widget` model with a # frozen_string_literal: true class Geo::WidgetRegistry < Geo::BaseRegistry - include Geo::ReplicableRegistry - # TODO: Include VerificationState in VerifiableRegistry - # https://gitlab.com/gitlab-org/gitlab/-/issues/298811 - include ::Gitlab::Geo::VerificationState + include ::Geo::ReplicableRegistry include ::Geo::VerifiableRegistry MODEL_CLASS = ::Widget @@ -943,7 +938,7 @@ For example, to add support for files referenced by a `Gizmos` model with a t.bigint :gizmo_id, null: false t.integer :state, default: 0, null: false, limit: 2 t.integer :retry_count, default: 0, limit: 2 - t.text :last_sync_failure + t.string :last_sync_failure, limit: 255 t.boolean :force_to_redownload t.boolean :missing_on_primary @@ -951,8 +946,6 @@ For example, to add support for files referenced by a `Gizmos` model with a t.index :retry_at t.index :state end - - add_text_limit :gizmo_registry, :last_sync_failure, 255 end def down diff --git a/doc/development/git_object_deduplication.md b/doc/development/git_object_deduplication.md index 00993cc2932..d9ff88aef60 100644 --- a/doc/development/git_object_deduplication.md +++ b/doc/development/git_object_deduplication.md @@ -1,7 +1,8 @@ --- -stage: none -group: unassigned +stage: Create +group: Gitaly 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 +type: reference --- # How Git object deduplication works in GitLab diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md index f352db918ed..745ec50bdcd 100644 --- a/doc/development/go_guide/index.md +++ b/doc/development/go_guide/index.md @@ -91,7 +91,7 @@ projects: - Avoid global variables, even in packages. By doing so you introduce side effects if the package is included multiple times. - Use `goimports` before committing. - [`goimports`](https://godoc.org/golang.org/x/tools/cmd/goimports) + [`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) is a tool that automatically formats Go source code using [`Gofmt`](https://golang.org/cmd/gofmt/), in addition to formatting import lines, adding missing ones and removing unreferenced ones. @@ -202,9 +202,9 @@ code readability and test output. ### Better output in tests When comparing expected and actual values in tests, use -[`testify/require.Equal`](https://godoc.org/github.com/stretchr/testify/require#Equal), -[`testify/require.EqualError`](https://godoc.org/github.com/stretchr/testify/require#EqualError), -[`testify/require.EqualValues`](https://godoc.org/github.com/stretchr/testify/require#EqualValues), +[`testify/require.Equal`](https://pkg.go.dev/github.com/stretchr/testify/require#Equal), +[`testify/require.EqualError`](https://pkg.go.dev/github.com/stretchr/testify/require#EqualError), +[`testify/require.EqualValues`](https://pkg.go.dev/github.com/stretchr/testify/require#EqualValues), and others to improve readability when comparing structs, errors, large portions of text, or JSON documents: @@ -363,12 +363,12 @@ There are a few guidelines one should follow when using the [Logrus](https://github.com/sirupsen/logrus) package: - When printing an error use - [WithError](https://godoc.org/github.com/sirupsen/logrus#WithError). For + [WithError](https://pkg.go.dev/github.com/sirupsen/logrus#WithError). For example, `logrus.WithError(err).Error("Failed to do something")`. - Since we use [structured logging](#structured-json-logging) we can log fields in the context of that code path, such as the URI of the request using - [`WithField`](https://godoc.org/github.com/sirupsen/logrus#WithField) or - [`WithFields`](https://godoc.org/github.com/sirupsen/logrus#WithFields). For + [`WithField`](https://pkg.go.dev/github.com/sirupsen/logrus#WithField) or + [`WithFields`](https://pkg.go.dev/github.com/sirupsen/logrus#WithFields). For example, `logrus.WithField("file", "/app/go").Info("Opening dir")`. If you have to log multiple keys, always use `WithFields` instead of calling `WithField` more than once. @@ -488,7 +488,7 @@ The following are some style guidelines that are specific to the Secure Team. ### Code style and format Use `goimports -local gitlab.com/gitlab-org` before committing. -[`goimports`](https://godoc.org/golang.org/x/tools/cmd/goimports) +[`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) is a tool that automatically formats Go source code using [`Gofmt`](https://golang.org/cmd/gofmt/), in addition to formatting import lines, adding missing ones and removing unreferenced ones. diff --git a/doc/development/graphql_guide/graphql_pro.md b/doc/development/graphql_guide/graphql_pro.md index 6f62d86af40..ca20d66dd87 100644 --- a/doc/development/graphql_guide/graphql_pro.md +++ b/doc/development/graphql_guide/graphql_pro.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # GraphQL Pro -GraphQL has become a key technology in GitLab and is implemented using the +GraphQL has become a key technology in GitLab and is implemented using the [GraphQL Ruby gem](https://graphql-ruby.org). As such, we've purchased a subscription to [GraphQL Pro](https://graphql.pro). @@ -15,7 +15,7 @@ The main purpose is for support. Per the website: > As a GraphQL::Pro customer, you get direct access to the GraphQL Ruby gem > creator and maintainer. Get prioritized support for issues and requests. -Note that we **cannot** use the Pro version directly in our product, since we are +Note that we **cannot** use the Pro version directly in our product, since we are an Open Core product - we can not require customers to purchase the Pro version, nor can we ship it. Details on the billing account and gem licensing can be found in the Engineering 1Password vault. diff --git a/doc/development/graphql_guide/index.md b/doc/development/graphql_guide/index.md index fd6d8992f94..4ecb34835aa 100644 --- a/doc/development/graphql_guide/index.md +++ b/doc/development/graphql_guide/index.md @@ -17,6 +17,6 @@ feedback, and suggestions. - [GraphQL API documentation style guide](../documentation/graphql_styleguide.md): documentation style guide for GraphQL. - [GraphQL API](../../api/graphql/index.md): user documentation for the GitLab GraphQL API. -- [GraphQL BatchLoader](batchloader.md): development documentation on the batchloader. +- [GraphQL BatchLoader](batchloader.md): development documentation on the BatchLoader. - [GraphQL pagination](pagination.md): development documentation on pagination. - [GraphQL Pro](graphql_pro.md): information on our GraphQL Pro subscription. diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md index 25dc854d2a3..7fb49521106 100644 --- a/doc/development/i18n/translation.md +++ b/doc/development/i18n/translation.md @@ -22,9 +22,17 @@ You may create a new account or use any of their supported sign in services. GitLab is being translated into many languages. -1. Select the language you would like to contribute translations to by clicking the flag +1. Find the language that you want to contribute to, in our + [GitLab Crowdin project](https://crowdin.com/project/gitlab-ee). + - If the language that you're looking for is available, proceed + to the next step. + - If the language you are looking for is not available, + [open an issue](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category%3AInternationalization). Notify our Crowdin + administrators by including `@gitlab-org/manage/import` in your issue. + in the issue. + - After the issue/Merge Request is complete, restart this procedure. 1. Next, you can view list of files and folders. - Click `gitlab.pot` to open the translation editor. + Select `gitlab.pot` to open the translation editor. ### Translation Editor diff --git a/doc/development/image_scaling.md b/doc/development/image_scaling.md index d447b6baf57..79687b66711 100644 --- a/doc/development/image_scaling.md +++ b/doc/development/image_scaling.md @@ -73,7 +73,7 @@ we simply follow the path we take to serve any ordinary upload. ### Workhorse Assuming Rails decided the request to be valid, Workhorse will take over. Upon receiving the `send-scaled-image` -instruction through the Rails response, a [special response injecter](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/master/internal/imageresizer/image_resizer.go) +instruction through the Rails response, a [special response injector](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/master/internal/imageresizer/image_resizer.go) will be invoked that knows how to rescale images. The only inputs it requires are the location of the image (a path if the image resides in block storage, or a URL to remote storage otherwise) and the desired width. Workhorse will handle the location transparently so Rails does not need to be concerned with where the image diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md index 16aba023fab..f54abfd17fd 100644 --- a/doc/development/integrations/jenkins.md +++ b/doc/development/integrations/jenkins.md @@ -8,6 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w This is a step by step guide on how to set up [Jenkins](https://www.jenkins.io/) on your local machine and connect to it from your GitLab instance. GitLab triggers webhooks on Jenkins, and Jenkins connects to GitLab using the API. By running both applications on the same machine, we can make sure they are able to access each other. +For configuring an existing Jenkins integration, read [Jenkins CI service](../../integration/jenkins.md). + ## Install Jenkins Install Jenkins and start the service using Homebrew. @@ -39,62 +41,20 @@ Jenkins uses the GitLab API and needs an access token. ## Configure Jenkins -Configure your GitLab API connection in Jenkins. - -1. Make sure the GitLab plugin is installed on Jenkins. You can manage plugins in **Manage Jenkins > Manage Plugins**. -1. Set up the GitLab connection: - 1. Go to **Manage Jenkins > Configure System**. - 1. Find the **GitLab** section and check the **Enable authentication for '/project' end-point** checkbox. -1. To add your credentials, click **Add** then choose **Jenkins Credential Provider**. -1. Choose **GitLab API token** as the type of token. -1. Paste your GitLab access token and click **Add**. -1. Choose your credentials from the dropdown menu. -1. Add your GitLab host URL. Normally `http://localhost:3000/`. -1. Click **Save Settings**. - -For more details, see [GitLab documentation about Jenkins CI](../../integration/jenkins.md). +To configure your GitLab API connection in Jenkins, read +[Configure the Jenkins server](../../integration/jenkins.md#configure-the-jenkins-server). ## Configure Jenkins Project -Set up the Jenkins project to run your build on. A **Freestyle** project is the easiest -option because the Jenkins plugin updates the build status on GitLab. In a **Pipeline** project, updating the status on GitLab needs to be configured in a script. - -1. On your Jenkins instance, go to **New Item**. -1. Pick a name, choose **Freestyle** or **Pipeline** and click **ok**. -1. Choose your GitLab connection from the dropdown. -1. Check the **Build when a change is pushed to GitLab** checkbox. -1. Check the following checkboxes: - - - **Accepted Merge Request Events** - - **Closed Merge Request Events** - -1. If you created a **Freestyle** project, choose **Publish build status to GitLab** in the **Post-build Actions** section. - - If you created a **Pipeline** project, updating the status on GitLab has to be done by the pipeline script. Add GitLab update steps as in this example: - - ```groovy - pipeline { - agent any - - stages { - stage('gitlab') { - steps { - echo 'Notify GitLab' - updateGitlabCommitStatus name: 'build', state: 'pending' - updateGitlabCommitStatus name: 'build', state: 'success' - } - } - } - } - ``` +To set up the Jenkins project you intend to run your build on, read +[Configure the Jenkins project](../../integration/jenkins.md#configure-the-jenkins-project). ## Configure your GitLab project -To activate the Jenkins service: +You can configure your integration between Jenkins and GitLab: -1. Go to your project's page, then **Settings > Integrations > Jenkins CI**. -1. Check the **Active** checkbox and the triggers for **Push** and **Merge request**. -1. Fill in your Jenkins host, project name, username and password and click **Test settings and save changes**. +- With the [recommended approach for Jenkins integration](../../integration/jenkins.md#recommended-jenkins-integration). +- [Using a webhook](../../integration/jenkins.md#webhook-integration). ## Test your setup diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md index bfe523ee390..860fd88612f 100644 --- a/doc/development/integrations/jira_connect.md +++ b/doc/development/integrations/jira_connect.md @@ -4,7 +4,7 @@ group: Ecosystem 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 --- -# Set up a development environment +# Set up a development environment **(FREE)** The following are required to install and test the app: diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md index 1d5aced5869..fda75dad119 100644 --- a/doc/development/integrations/secure.md +++ b/doc/development/integrations/secure.md @@ -89,7 +89,7 @@ it's declared under the `reports:sast` key in the job definition, not because of ### Policies Certain GitLab workflows, such as [AutoDevOps](../../topics/autodevops/customize.md#disable-jobs), -define variables to indicate that given scans should be disabled. You can check for this by looking +define CI/CD variables to indicate that given scans should be disabled. You can check for this by looking for variables such as `DEPENDENCY_SCANNING_DISABLED`, `CONTAINER_SCANNING_DISABLED`, `SAST_DISABLED`, and `DAST_DISABLED`. If appropriate based on the scanner type, you should then disable running the custom scanner. @@ -97,7 +97,7 @@ disable running the custom scanner. GitLab also defines a `CI_PROJECT_REPOSITORY_LANGUAGES` variable, which provides the list of languages in the repository. Depending on this value, your scanner may or may not do something different. Language detection currently relies on the [`linguist`](https://github.com/github/linguist) Ruby gem. -See [GitLab CI/CD predefined variables](../../ci/variables/predefined_variables.md). +See the [predefined CI/CD variables](../../ci/variables/predefined_variables.md). #### Policy checking example @@ -170,23 +170,23 @@ It also generates text output on the standard output and standard error streams, ### Variables -All CI variables are passed to the scanner as environment variables. -The scanned project is described by the [predefined CI variables](../../ci/variables/README.md). +All CI/CD variables are passed to the scanner as environment variables. +The scanned project is described by the [predefined CI/CD variables](../../ci/variables/README.md). #### SAST and Dependency Scanning -SAST and Dependency Scanning scanners must scan the files in the project directory, given by the `CI_PROJECT_DIR` variable. +SAST and Dependency Scanning scanners must scan the files in the project directory, given by the `CI_PROJECT_DIR` CI/CD variable. #### Container Scanning In order to be consistent with the official Container Scanning for GitLab, scanners must scan the Docker image whose name and tag are given by `CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG`, respectively. If the `DOCKER_IMAGE` -variable is provided, then the `CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG` variables +CI/CD variable is provided, then the `CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG` variables are ignored, and the image specified in the `DOCKER_IMAGE` variable is scanned instead. If not provided, `CI_APPLICATION_REPOSITORY` should default to -`$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG`, which is a combination of predefined CI variables. +`$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG`, which is a combination of predefined CI/CD variables. `CI_APPLICATION_TAG` should default to `CI_COMMIT_SHA`. The scanner should sign in the Docker registry @@ -197,13 +197,13 @@ If these are not defined, then the scanner should use #### Configuration files While scanners may use `CI_PROJECT_DIR` to load specific configuration files, -it is recommended to expose configuration as environment variables, not files. +it is recommended to expose configuration as CI/CD variables, not files. ### Output file -Like any artifact uploaded to the GitLab CI/CD, +Like any artifact uploaded to GitLab CI/CD, the Secure report generated by the scanner must be written in the project directory, -given by the `CI_PROJECT_DIR` environment variable. +given by the `CI_PROJECT_DIR` CI/CD variable. It is recommended to name the output file after the type of scanning, and to use `gl-` as a prefix. Since all Secure reports are JSON files, it is recommended to use `.json` as a file extension. @@ -242,7 +242,7 @@ Also, we recommend prefixing error messages with `[ERRO]`, warnings with `[WARN] #### Logging level The scanner should filter out a log message if its log level is lower than the -one set in the `SECURE_LOG_LEVEL` variable. For instance, `info` and `warn` +one set in the `SECURE_LOG_LEVEL` CI/CD variable. For instance, `info` and `warn` messages should be skipped when `SECURE_LOG_LEVEL` is set to `error`. Accepted values are as follows, listed from highest to lowest: @@ -263,14 +263,14 @@ and what `bundle audit` writes to the standard output. If the command line fails, then it should be logged with the `error` log level; this makes it possible to debug the problem without having to change the log level to `debug` and rerun the scanning job. -#### common logutil package +#### common `logutil` package If you are using [go](https://golang.org/) and [common](https://gitlab.com/gitlab-org/security-products/analyzers/common), -then it is suggested that you use [logrus](https://github.com/Sirupsen/logrus) -and [common's logutil package](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil) -to configure the formatter for [logrus](https://github.com/Sirupsen/logrus). -See the [logutil README.md](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil/README.md) +then it is suggested that you use [Logrus](https://github.com/Sirupsen/logrus) +and [common's `logutil` package](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil) +to configure the formatter for [Logrus](https://github.com/Sirupsen/logrus). +See the [`logutil` README](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil/README.md) ## Report @@ -548,7 +548,7 @@ of the available SAST Analyzers and what data is currently available. The `remediations` field of the report is an array of remediation objects. Each remediation describes a patch that can be applied to -[automatically fix](../../user/application_security/#automatic-remediation-for-vulnerabilities) +[automatically fix](../../user/application_security/#apply-an-automatic-remediation-for-a-vulnerability) a set of vulnerabilities. Here is an example of a report that contains remediations. diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md index 364e18ad015..17bce13583c 100644 --- a/doc/development/integrations/secure_partner_integration.md +++ b/doc/development/integrations/secure_partner_integration.md @@ -13,7 +13,7 @@ guidelines so you can build an integration that fits with the workflow GitLab users are already familiar with. This page also provides resources for the technical work associated -with [onboarding as a partner](https://about.gitlab.com/partners/integrate/). +with [onboarding as a partner](https://about.gitlab.com/partners/technology-partners/integrate/). The steps below are a high-level view of what needs to be done to complete an integration as well as linking to more detailed resources for how to do so. @@ -101,7 +101,7 @@ and complete an integration with the Secure stage. - Users can interact with the findings from your artifact within their workflow. They can dismiss the findings or accept them and create a backlog issue. - To automatically create issues without user interaction, use the [issue API](../../api/issues.md). 1. Optional: Provide auto-remediation steps: - - If you specified `remediations` in your artifact, it is proposed through our [automatic remediation](../../user/application_security/index.md#automatic-remediation-for-vulnerabilities) + - If you specified `remediations` in your artifact, it is proposed through our [automatic remediation](../../user/application_security/index.md#apply-an-automatic-remediation-for-a-vulnerability) interface. 1. Demo the integration to GitLab: - After you have tested and are ready to demo your integration please diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md index dce0877b1b7..7c4f869d1a7 100644 --- a/doc/development/internal_api.md +++ b/doc/development/internal_api.md @@ -35,12 +35,12 @@ This is called by [Gitaly](https://gitlab.com/gitlab-org/gitaly) and [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell) to check access to a repository. -When called from GitLab Shell no changes are passed and the internal -API replies with the information needed to pass the request on to -Gitaly. +- **When called from GitLab Shell**: No changes are passed, and the internal + API replies with the information needed to pass the request on to Gitaly. +- **When called from Gitaly in a `pre-receive` hook**: The changes are passed + and validated to determine if the push is allowed. -When called from Gitaly in a `pre-receive` hook the changes are passed -and those are validated to determine if the push is allowed. +Calls are limited to 50 seconds each. ```plaintext POST /internal/allowed @@ -470,7 +470,7 @@ curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "A ## Subscriptions -The subscriptions endpoint is used by `[customers.gitlab.com](https://gitlab.com/gitlab-org/customers-gitlab-com)` (CustomersDot) +The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`) in order to apply subscriptions including trials, and add-on purchases, for personal namespaces or top-level groups within GitLab.com. ### Creating a subscription @@ -488,7 +488,7 @@ POST /namespaces/:id/gitlab_subscription | `plan_code` | string | no | Subscription tier code | | `seats` | integer | no | Number of seats in subscription | | `max_seats_used` | integer | no | Highest number of active users in the last month | -| `auto_renew` | boolean | no | Whether subscription will auto renew on end date | +| `auto_renew` | boolean | no | Whether subscription auto-renews on end date | | `trial` | boolean | no | Whether subscription is a trial | | `trial_starts_on` | date | no | Start date of trial | | `trial_ends_on` | date | no | End date of trial | @@ -539,7 +539,7 @@ PUT /namespaces/:id/gitlab_subscription | `plan_code` | string | no | Subscription tier code | | `seats` | integer | no | Number of seats in subscription | | `max_seats_used` | integer | no | Highest number of active users in the last month | -| `auto_renew` | boolean | no | Whether subscription will auto renew on end date | +| `auto_renew` | boolean | no | Whether subscription auto-renews on end date | | `trial` | boolean | no | Whether subscription is a trial | | `trial_starts_on` | date | no | Start date of trial. Required if trial is true. | | `trial_ends_on` | date | no | End date of trial | diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md index 377e31f6ab7..a9fc0414297 100644 --- a/doc/development/licensed_feature_availability.md +++ b/doc/development/licensed_feature_availability.md @@ -4,7 +4,7 @@ group: License 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 --- -# Licensed feature availability **(STARTER)** +# Licensed feature availability As of GitLab 9.4, we've been supporting a simplified version of licensed feature availability checks via `ee/app/models/license.rb`, both for @@ -17,9 +17,9 @@ feature such as [Related issues](../user/project/issues/related_issues.md) or [Service Desk](../user/project/service_desk.md), it should be restricted on namespace scope. -1. Add the feature symbol on `EES_FEATURES`, `EEP_FEATURES` or `EEU_FEATURES` constants in - `ee/app/models/license.rb`. Note on `ee/app/models/ee/namespace.rb` that _Bronze_ GitLab.com - features maps to on-premise _EES_, _Silver_ to _EEP_ and _Gold_ to _EEU_. +1. Add the feature symbol on `EES_FEATURES`, `EEP_FEATURES`, or `EEU_FEATURES` constants in + `ee/app/models/license.rb`. Note that the prefix `EES` signifies Starter, `EEP` signifies + Premium, and `EEU` signifies Ultimate. 1. Check using: ```ruby @@ -35,7 +35,7 @@ the instance license. 1. Add the feature symbol on `EES_FEATURES`, `EEP_FEATURES` or `EEU_FEATURES` constants in `ee/app/models/license.rb`. -1. Add the same feature symbol to `GLOBAL_FEATURES` +1. Add the same feature symbol to `GLOBAL_FEATURES`. 1. Check using: ```ruby diff --git a/doc/development/maintenance_mode.md b/doc/development/maintenance_mode.md index 6b5a6045bb9..f05a731a331 100644 --- a/doc/development/maintenance_mode.md +++ b/doc/development/maintenance_mode.md @@ -13,7 +13,7 @@ GitLab Maintenance Mode **only** blocks writes from HTTP and SSH requests at the - [the read-only database method](https://gitlab.com/gitlab-org/gitlab/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/database.rb#L13), which toggles special behavior when we are not allowed to write to the database. [Search the codebase for `Gitlab::Database.read_only?`.](https://gitlab.com/search?utf8=%E2%9C%93&search=Gitlab%3A%3ADatabase.read_only%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=) - [the read-only middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/middleware/read_only/controller.rb), where HTTP requests that cause database writes are blocked, unless explicitly allowed. -- [Git push access via SSH is denied](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/git_access.rb#L13) by returning 401 when `gitlab-shell` POSTs to `/internal/allowed` to [check if access is allowed](internal_api.md#git-authentication). +- [Git push access via SSH is denied](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/git_access.rb#L13) by returning 401 when `gitlab-shell` POSTs to [`/internal/allowed`](internal_api.md) to [check if access is allowed](internal_api.md#git-authentication). - [Container registry authentication service](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/app/services/ee/auth/container_registry_authentication_service.rb#L12), where updates to the container registry are blocked. The database itself is not in read-only mode (except in a Geo secondary site) and can be written by sources other than the ones blocked. diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md index 8d5b2db828e..50362269c1b 100644 --- a/doc/development/merge_request_performance_guidelines.md +++ b/doc/development/merge_request_performance_guidelines.md @@ -459,7 +459,7 @@ Performance deficiencies should be addressed right away after we merge initial changes. Read more about when and how feature flags should be used in -[Feature flags in GitLab development](feature_flags/process.md#feature-flags-in-gitlab-development). +[Feature flags in GitLab development](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle#feature-flags-in-gitlab-development). ## Storage diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index e1205346585..fcecc556052 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -374,7 +374,7 @@ standard Rails migration helper methods. Calling more than one migration helper is not a problem if they're executed on the same table. Using the `with_lock_retries` helper method is advised when a database -migration involves one of the [high-traffic tables](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3). +migration involves one of the [high-traffic tables](#high-traffic-tables). Example changes: @@ -605,9 +605,10 @@ When adding a foreign-key constraint to an existing column in a non-empty table, we have to employ `add_concurrent_foreign_key` and `add_concurrent_index` instead of `add_reference`. -For an empty table (such as a fresh one), it is recommended to use -`add_reference` in a single-transaction migration, combining it with other -operations that don't require `disable_ddl_transaction!`. +If you have a new or empty table that doesn't reference a +[high-traffic table](#high-traffic-tables), +we recommend that you use `add_reference` in a single-transaction migration. You can +combine it with other operations that don't require `disable_ddl_transaction!`. You can read more about adding [foreign key constraints to an existing column](database/add_foreign_key_to_existing_column.md). @@ -708,11 +709,8 @@ Dropping a database table is uncommon, and the `drop_table` method provided by Rails is generally considered safe. Before dropping the table, please consider the following: -If your table has foreign keys on a high-traffic table (like `projects`), then -the `DROP TABLE` statement might fail with **statement timeout** error. Determining -what tables are high traffic can be difficult. Self-managed instances might -use different features of GitLab with different usage patterns, thus making -assumptions based on GitLab.com is not enough. +If your table has foreign keys on a [high-traffic table](#high-traffic-tables) (like `projects`), then +the `DROP TABLE` statement is likely to stall concurrent traffic until it fails with **statement timeout** error. Table **has no records** (feature was never in use) and **no foreign keys**: @@ -1027,3 +1025,20 @@ D, [2020-07-06T00:37:12.653459 #130101] DEBUG -- : AddAndSeedMyColumn::User Up D, [2020-07-06T00:37:12.653648 #130101] DEBUG -- : ↳ config/initializers/config_initializers_active_record_locking.rb:13:in `_update_row' == 20200705232821 AddAndSeedMyColumn: migrated (0.1706s) ===================== ``` + +## High traffic tables + +Here's a list of current [high-traffic tables](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml). + +Determining what tables are high-traffic can be difficult. Self-managed instances might use +different features of GitLab with different usage patterns, thus making assumptions based +on GitLab.com not enough. + +To identify a high-traffic table for GitLab.com the following measures are considered. +Note that the metrics linked here are GitLab-internal only: + +- [Read operations](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_seq_tup_read%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_scan%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_tup_fetch%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1) +- [Number of records](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_n_live_tup%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1) +- [Size](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_total_relation_size_bytes%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1) is greater than 10 GB + +Any table which has some high read operation compared to current [high-traffic tables](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L4) might be a good candidate. diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md index 25f4b3b5699..ff831bfa348 100644 --- a/doc/development/multi_version_compatibility.md +++ b/doc/development/multi_version_compatibility.md @@ -207,7 +207,7 @@ variable `CI_NODE_TOTAL` being an integer failed. This was caused because after 1. Old code: Runners requested a job from an API node that is running the previous version. 1. As a result, the [new code](https://gitlab.com/gitlab-org/gitlab/blob/42b82a9a3ac5a96f9152aad6cbc583c42b9fb082/app/models/concerns/ci/contextable.rb#L104) was not run on the API server. The runner's request failed because the -older API server tried return the `CI_NODE_TOTAL` CI variable, but +older API server tried return the `CI_NODE_TOTAL` CI/CD variable, but instead of sending an integer value (e.g. 9), it sent a serialized `Hash` value (`{:number=>9, :total=>9}`). diff --git a/doc/development/namespaces_storage_statistics.md b/doc/development/namespaces_storage_statistics.md index 373b1e38dfc..587e1091e77 100644 --- a/doc/development/namespaces_storage_statistics.md +++ b/doc/development/namespaces_storage_statistics.md @@ -140,7 +140,7 @@ Even though this approach would make aggregating much easier, it has some major - We'd have to migrate **all namespaces** by adding and filling a new column. Because of the size of the table, dealing with time/cost would be significant. The background migration would take approximately `153h`, see <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29772>. - Background migration has to be shipped one release before, delaying the functionality by another milestone. -### Attempt E (final): Update the namespace storage statistics in async way +### Attempt E (final): Update the namespace storage statistics asynchronously This approach consists of continuing to use the incremental statistics updates we already have, but we refresh them through Sidekiq jobs and in different transactions: @@ -149,7 +149,7 @@ but we refresh them through Sidekiq jobs and in different transactions: 1. Whenever the statistics of a project changes, insert a row into `namespace_aggregation_schedules` - We don't insert a new row if there's already one related to the root namespace. - Keeping in mind the length of the transaction that involves updating `project_statistics`(<https://gitlab.com/gitlab-org/gitlab/-/issues/29070>), the insertion should be done in a different transaction and through a Sidekiq Job. -1. After inserting the row, we schedule another worker to be executed async at two different moments: +1. After inserting the row, we schedule another worker to be executed asynchronously at two different moments: - One enqueued for immediate execution and another one scheduled in `1.5h` hours. - We only schedule the jobs, if we can obtain a `1.5h` lease on Redis on a key based on the root namespace ID. - If we can't obtain the lease, it indicates there's another aggregation already in progress, or scheduled in no more than `1.5h`. @@ -161,7 +161,7 @@ but we refresh them through Sidekiq jobs and in different transactions: This implementation has the following benefits: -- All the updates are done async, so we're not increasing the length of the transactions for `project_statistics`. +- All the updates are done asynchronously, so we're not increasing the length of the transactions for `project_statistics`. - We're doing the update in a single SQL query. - It is compatible with PostgreSQL and MySQL. - No background migration required. diff --git a/doc/development/new_fe_guide/development/components.md b/doc/development/new_fe_guide/development/components.md index 1d56419028e..ec714c9c26f 100644 --- a/doc/development/new_fe_guide/development/components.md +++ b/doc/development/new_fe_guide/development/components.md @@ -19,7 +19,7 @@ D3 is very popular across many projects outside of GitLab: - [The New York Times](https://archive.nytimes.com/www.nytimes.com/interactive/2012/02/13/us/politics/2013-budget-proposal-graphic.html) - [plot.ly](https://plotly.com/) -- [Droptask](https://www.ayoa.com/previously-droptask/) +- [Ayoa](https://www.ayoa.com/previously-droptask/) Within GitLab, D3 has been used for the following notable features diff --git a/doc/development/new_fe_guide/tips.md b/doc/development/new_fe_guide/tips.md index d38e261b99f..c60d70b3b16 100644 --- a/doc/development/new_fe_guide/tips.md +++ b/doc/development/new_fe_guide/tips.md @@ -16,18 +16,18 @@ yarn clean ## Creating feature flags in development -The process for creating a feature flag is the same as [enabling a feature flag in development](../feature_flags/development.md#enabling-a-feature-flag-locally-in-development). +The process for creating a feature flag is the same as [enabling a feature flag in development](../feature_flags/index.md#enabling-a-feature-flag-locally-in-development). Your feature flag can now be: -- [Made available to the frontend](../feature_flags/development.md#frontend) via the `gon` -- Queried in [tests](../feature_flags/development.md#feature-flags-in-tests) +- [Made available to the frontend](../feature_flags/index.md#frontend) via the `gon` +- Queried in [tests](../feature_flags/index.md#feature-flags-in-tests) - Queried in HAML templates and Ruby files via the `Feature.enabled?(:my_shiny_new_feature_flag)` method ### More on feature flags - [Deleting a feature flag](../../api/features.md#delete-a-feature) -- [Manage feature flags](../feature_flags/process.md) +- [Manage feature flags](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle) - [Feature flags API](../../api/features.md) ## Running tests locally diff --git a/doc/development/packages.md b/doc/development/packages.md index 2476c876b77..e8c326da974 100644 --- a/doc/development/packages.md +++ b/doc/development/packages.md @@ -6,20 +6,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Packages -This document guides you through adding another [package management system](../administration/packages/index.md) support to GitLab. +This document guides you through adding support to GitLab for a new a [package management system](../administration/packages/index.md). -See already supported package types in [Packages documentation](../administration/packages/index.md) +See the already supported formats in the [Packages & Registries documentation](../user/packages/index.md) -Since GitLab packages' UI is pretty generic, it is possible to add basic new -package system support with solely backend changes. This guide is superficial and does -not cover the way the code should be written. However, you can find a good example -by looking at the following merge requests: +It is possible to add a new format with only backend changes. +This guide is superficial and does not cover the way the code should be written. +However, you can find a good example by looking at the following merge requests: -- [npm registry support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8673). -- [Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6607). -- [Composer repository for PHP dependencies](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22415). -- [Terraform modules registry](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834). -- [Instance-level endpoint for Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8757). +- [npm registry support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8673) +- [Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6607) +- [Instance-level API for Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8757) +- [NuGet group-level API](https://gitlab.com/gitlab-org/gitlab/-/issues/36423) ## General information @@ -60,26 +58,13 @@ project are visible. Alternatively, a group-level endpoint may be used to allow within a given group. Lastly, an instance-level endpoint can be used to allow visibility to all packages within an entire GitLab instance. -Using group and project level endpoints allows for more flexibility in package naming, however, more remotes -have to be managed. Using instance level endpoints requires [stricter naming conventions](#naming-conventions). +As an MVC, we recommend beginning with a project-level endpoint. A typical iteration plan for remote hierarchies is to go from: -The current state of existing package registries availability is: +- Publish and install in a project +- Install from a group +- Publish and install in an Instance (this is for Self-Managed customers) -| Repository Type | Project Level | Group Level | Instance Level | -|------------------|---------------|-------------|----------------| -| Maven | Yes | Yes | Yes | -| Conan | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/11679) | Yes | -| npm | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) | -| NuGet | Yes | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36425) | -| PyPI | Yes | No | No | -| Go | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/213900) | No - [open-issue](https://gitlab.com/gitlab-org/gitlab/-/issues/213902) | -| Composer | Yes | Yes | No | -| Generic | Yes | No | No | - -NOTE: -npm is currently a hybrid of the instance level and group level. -It is using the top-level group or namespace as the defining portion of the name -(for example, `@my-group-name/my-package-name`). +Using instance-level endpoints requires [stricter naming conventions](#naming-conventions). NOTE: Composer package naming scope is Instance Level. @@ -116,8 +101,8 @@ Packages can be configured to use object storage, therefore your code must suppo The way new package systems are integrated in GitLab is using an [MVC](https://about.gitlab.com/handbook/values/#minimum-viable-change-mvc). Therefore, the first iteration should support the bare minimum user actions: -- Authentication -- Uploading a package +- Authentication with a GitLab job, personal access, project access, or deploy token +- Uploading a package and displaying basic metadata in the user interface - Pulling a package - Required actions @@ -137,7 +122,7 @@ There are usually 2 phases for the MVC: When implementing a new package manager, it is tempting to create one large merge request containing all of the necessary endpoints and services necessary to support basic usage. Instead, put the -API endpoints behind a [feature flag](feature_flags/development.md) and +API endpoints behind a [feature flag](feature_flags/index.md) and submit each endpoint or behavior (download, upload, etc) in a different merge request to shorten the review process. @@ -242,6 +227,17 @@ create the package record. Workhorse provides a variety of file metadata such as For testing purposes, you may want to [enable object storage](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/object_storage.md) in your local development environment. +#### File size limits + +Files uploaded to the GitLab Package Registry are [limited by format](../administration/instance_limits.md#package-registry-limits). +On GitLab.com, these are typically set to 5GB to help prevent timeout issues and abuse. + +When a new package type is added to the `Packages::Package` model, a size limit must be added +similar to [this example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52639/diffs#382f879fb09b0212e3cedd99e6c46e2083867216), +or the [related test](https://gitlab.com/gitlab-org/gitlab/-/blob/fe4ba43766781371cebfacd78364a1de762917cd/spec/models/packages/package_spec.rb#L761) +must be updated if file size limits do not apply. The only reason a size limit does not apply is if +the package format does not upload and store package files. + #### Rate Limits on GitLab.com Package manager clients can make rapid requests that exceed the diff --git a/doc/development/performance.md b/doc/development/performance.md index 3b4525dc8ee..e93dc26e4fc 100644 --- a/doc/development/performance.md +++ b/doc/development/performance.md @@ -256,7 +256,7 @@ The following configuration options can be configured: - `STACKPROF_MODE`: See [sampling modes](https://github.com/tmm1/stackprof#sampling). Defaults to `cpu`. - `STACKPROF_INTERVAL`: Sampling interval. Unit semantics depend on `STACKPROF_MODE`. - For `object` mode this is a per-event interval (every `n`th event is sampled) + For `object` mode this is a per-event interval (every `nth` event is sampled) and defaults to `1000`. For other modes such as `cpu` this is a frequency and defaults to `10000` μs (100hz). - `STACKPROF_FILE_PREFIX`: File path prefix where profiles are stored. Defaults @@ -293,7 +293,7 @@ worker processes), selecting the latter. For Sidekiq, the signal can be sent to the `sidekiq-cluster` process via `pkill -USR2 bin/sidekiq-cluster`, which forwards the signal to all Sidekiq -children. Alternatively, you can also select a specific pid of interest. +children. Alternatively, you can also select a specific PID of interest. Production profiles can be especially noisy. It can be helpful to visualize them as a [flame graph](https://github.com/brendangregg/FlameGraph). This can be done @@ -306,7 +306,7 @@ bundle exec stackprof --stackcollapse /tmp/stackprof.55769.c6c3906452.profile | ## RSpec profiling The GitLab development environment also includes the -[rspec_profiling](https://github.com/foraker/rspec_profiling) gem, which is used +[`rspec_profiling`](https://github.com/foraker/rspec_profiling) gem, which is used to collect data on spec execution times. This is useful for analyzing the performance of the test suite itself, or seeing how the performance of a spec may have changed over time. @@ -347,13 +347,112 @@ example, you can find which tests take longest to run or which execute the most queries. This can be handy for optimizing our tests or identifying performance issues in our code. -## Memory profiling +## Memory optimization -We can use two approaches, often in combination, to track down memory issues: +We can use a set of different techniques, often in combination, to track down memory issues: - Leaving the code intact and wrapping a profiler around it. +- Use memory allocation counters for requests and services. - Monitor memory usage of the process while disabling/enabling different parts of the code we suspect could be problematic. +### Memory allocations + +Ruby shipped with GitLab includes a special patch to allow [tracing memory allocations](https://gitlab.com/gitlab-org/gitlab/-/issues/296530). +This patch is available by default for +[Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4948), +[CNG](https://gitlab.com/gitlab-org/build/CNG/-/merge_requests/591), +[GitLab CI](https://gitlab.com/gitlab-org/gitlab-build-images/-/merge_requests/355), +[GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit/-/merge_requests/149) +and can additionally be enabled for [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/advanced.md#apply-custom-patches-for-ruby). + +This patch provides a set of 3 metrics that makes it easier to understand efficiency of memory usage for a given codepath: + +- `mem_objects`: the number of objects allocated. +- `mem_bytes`: the number of bytes allocated by malloc. +- `mem_mallocs`: the number of malloc allocations. + +The number of objects and bytes allocated impact how often GC cycles happen. +Fewer objects allocations result in a significantly more responsive application. + +It is advised that web server requests do not allocate more than `100k mem_objects` +and `100M mem_bytes`. You can view the current usage on [GitLab.com](https://log.gprd.gitlab.net/goto/3a9678bb595e3f89a0c7b5c61bcc47b9). + +#### Checking memory pressure of own code + +There are two ways of measuring your own code: + +1. Review `api_json.log`, `development_json.log`, `sidekiq.log` that includes memory allocation counters. +1. Use `Gitlab::Memory::Instrumentation.with_memory_allocations` for a given codeblock and log it. +1. Use [Measuring module](service_measurement.md) + +```json +{"time":"2021-02-15T11:20:40.821Z","severity":"INFO","duration_s":0.27412,"db_duration_s":0.05755,"view_duration_s":0.21657,"status":201,"method":"POST","path":"/api/v4/projects/user/1","mem_objects":86705,"mem_bytes":4277179,"mem_mallocs":22693,"correlation_id":"...} +``` + +#### Different types of allocations + +The `mem_*` values represent different aspects of how objects and memory are allocated in Ruby: + +- The following example will create around of `1000` of `mem_objects` since strings + can be frozen, and while the underlying string object remains the same, we still need to allocate 1000 references to this string: + + ```ruby + Gitlab::Memory::Instrumentation.with_memory_allocations do + 1_000.times { '0123456789' } + end + + => {:mem_objects=>1001, :mem_bytes=>0, :mem_mallocs=>0} + ``` + +- The following example will create around of `1000` of `mem_objects`, as strings are created dynamically. + Each of them will not allocate additional memory, as they fit into Ruby slot of 40 bytes: + + ```ruby + Gitlab::Memory::Instrumentation.with_memory_allocations do + s = '0' + 1_000.times { s * 23 } + end + + => {:mem_objects=>1002, :mem_bytes=>0, :mem_mallocs=>0} + ``` + +- The following example will create around of `1000` of `mem_objects`, as strings are created dynamically. + Each of them will allocate additional memory as strings are larger than Ruby slot of 40 bytes: + + ```ruby + Gitlab::Memory::Instrumentation.with_memory_allocations do + s = '0' + 1_000.times { s * 24 } + end + + => {:mem_objects=>1002, :mem_bytes=>32000, :mem_mallocs=>1000} + ``` + +- The following example will allocate over 40kB of data, and perform only a single memory allocation. + The existing object will be reallocated/resized on subsequent iterations: + + ```ruby + Gitlab::Memory::Instrumentation.with_memory_allocations do + str = '' + append = '0123456789012345678901234567890123456789' # 40 bytes + 1_000.times { str.concat(append) } + end + => {:mem_objects=>3, :mem_bytes=>49152, :mem_mallocs=>1} + ``` + +- The following example will create over 1k of objects, perform over 1k of allocations, each time mutating the object. + This does result in copying a lot of data and perform a lot of memory allocations + (as represented by `mem_bytes` counter) indicating very inefficient method of appending string: + + ```ruby + Gitlab::Memory::Instrumentation.with_memory_allocations do + str = '' + append = '0123456789012345678901234567890123456789' # 40 bytes + 1_000.times { str += append } + end + => {:mem_objects=>1003, :mem_bytes=>21968752, :mem_mallocs=>1000} + ``` + ### Using Memory Profiler We can use `memory_profiler` for profiling. @@ -409,7 +508,7 @@ Fragmented Ruby heap snapshot could look like this: ![Ruby heap fragmentation](img/memory_ruby_heap_fragmentation.png) -Memory fragmentation could be reduced by tuning GC parameters as described in [this post by Nate Berkopec](https://www.speedshop.co/2017/12/04/malloc-doubles-ruby-memory.html). This should be considered as a tradeoff, as it may affect overall performance of memory allocation and GC cycles. +Memory fragmentation could be reduced by tuning GC parameters [as described in this post](https://www.speedshop.co/2017/12/04/malloc-doubles-ruby-memory.html). This should be considered as a tradeoff, as it may affect overall performance of memory allocation and GC cycles. ## Importance of Changes diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index 4d931899da6..aa3f2e6791a 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -19,7 +19,7 @@ as much as possible. ## Overview -Pipelines for the GitLab project are created using the [`workflow:rules` keyword](../ci/yaml/README.md#workflowrules) +Pipelines for the GitLab project are created using the [`workflow:rules` keyword](../ci/yaml/README.md#workflow) feature of the GitLab CI/CD. Pipelines are always created for the following scenarios: @@ -29,7 +29,7 @@ Pipelines are always created for the following scenarios: - Tags. - Stable, `auto-deploy`, and security branches. -Pipeline creation is also affected by the following CI variables: +Pipeline creation is also affected by the following CI/CD variables: - If `$FORCE_GITLAB_CI` is set, pipelines are created. - If `$GITLAB_INTERNAL` is not set, pipelines are not created. @@ -414,10 +414,10 @@ The `rspec fail-fast` is a no-op if there are more than 10 test files related to Merge Request. This prevents `rspec fail-fast` duration from exceeding the average `rspec` job duration and defeating its purpose. -This number can be overridden by setting a CI variable named `RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD`. +This number can be overridden by setting a CI/CD variable named `RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD`. NOTE: -This experiment is only enabled when the CI variable `RSPEC_FAIL_FAST_ENABLED=true` is set. +This experiment is only enabled when the CI/CD variable `RSPEC_FAIL_FAST_ENABLED=true` is set. #### Determining related test files in a Merge Request @@ -426,7 +426,7 @@ We are using a custom mapping between source file to test files, maintained in t ### PostgreSQL versions testing -Even though [Omnibus defaults to PG12 for new installs and upgrades](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.md), +Even though [Omnibus defaults to PG12 for new installs and upgrades](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.html), our test suite is currently running against PG11, since GitLab.com still runs on PG11. We do run our test suite against PG12 on nightly scheduled pipelines as well as upon specific @@ -531,8 +531,7 @@ several reasons: The pre-clone step works by using the `CI_PRE_CLONE_SCRIPT` variable [defined by GitLab.com shared runners](../user/gitlab_com/index.md#pre-clone-script). -The `CI_PRE_CLONE_SCRIPT` is currently defined as a project CI/CD -variable: +The `CI_PRE_CLONE_SCRIPT` is currently defined as a project CI/CD variable: ```shell echo "Downloading archived master..." @@ -638,7 +637,7 @@ Some of the jobs are using images from Docker Hub, where we also use `${GITLAB_DEPENDENCY_PROXY}` as a prefix to the image path, so that we pull images from our [Dependency Proxy](../user/packages/dependency_proxy/index.md). -`${GITLAB_DEPENDENCY_PROXY}` is a group variable defined in +`${GITLAB_DEPENDENCY_PROXY}` is a group CI/CD variable defined in [`gitlab-org`](https://gitlab.com/gitlab-org) as `${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/`. This means when we use an image defined as: @@ -653,7 +652,7 @@ Docker Hub unless `${GITLAB_DEPENDENCY_PROXY}` is also defined there. ### Default variables -In addition to the [predefined variables](../ci/variables/predefined_variables.md), +In addition to the [predefined CI/CD variables](../ci/variables/predefined_variables.md), each pipeline includes default variables defined in [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml). @@ -674,12 +673,12 @@ that are scoped to a single [configuration keyword](../ci/yaml/README.md#job-key | `.qa-cache` | Allows a job to use a default `cache` definition suitable for QA tasks. | | `.yarn-cache` | Allows a job to use a default `cache` definition suitable for frontend jobs that do a `yarn install`. | | `.assets-compile-cache` | Allows a job to use a default `cache` definition suitable for frontend jobs that compile assets. | -| `.use-pg11` | Allows a job to use the `postgres:11.6` and `redis:4.0-alpine` services. | -| `.use-pg11-ee` | Same as `.use-pg11` but also use the `docker.elastic.co/elasticsearch/elasticsearch:7.9.2` services. | -| `.use-pg12` | Allows a job to use the `postgres:12` and `redis:4.0-alpine` services. | -| `.use-pg12-ee` | Same as `.use-pg12` but also use the `docker.elastic.co/elasticsearch/elasticsearch:7.9.2` services. | +| `.use-pg11` | Allows a job to run the `postgres` 11 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). | +| `.use-pg11-ee` | Same as `.use-pg11` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). | +| `.use-pg12` | Allows a job to use the `postgres` 12 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). | +| `.use-pg12-ee` | Same as `.use-pg12` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). | | `.use-kaniko` | Allows a job to use the `kaniko` tool to build Docker images. | -| `.as-if-foss` | Simulate the FOSS project by setting the `FOSS_ONLY='1'` environment variable. | +| `.as-if-foss` | Simulate the FOSS project by setting the `FOSS_ONLY='1'` CI/CD variable. | | `.use-docker-in-docker` | Allows a job to use Docker in Docker. | ### `rules`, `if:` conditions and `changes:` patterns @@ -704,13 +703,13 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch | `if-not-canonical-namespace` | Matches if the project isn't in the canonical (`gitlab-org/`) or security (`gitlab-org/security`) namespace. | Use to create a job for forks (by using `when: on_success|manual`), or **not** create a job for forks (by using `when: never`). | | `if-not-ee` | Matches if the project isn't EE (i.e. project name isn't `gitlab` or `gitlab-ee`). | Use to create a job only in the FOSS project (by using `when: on_success|manual`), or **not** create a job if the project is EE (by using `when: never`). | | `if-not-foss` | Matches if the project isn't FOSS (i.e. project name isn't `gitlab-foss`, `gitlab-ce`, or `gitlabhq`). | Use to create a job only in the EE project (by using `when: on_success|manual`), or **not** create a job if the project is FOSS (by using `when: never`). | -| `if-default-refs` | Matches if the pipeline is for `master`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. | -| `if-master-refs` | Matches if the current branch is `master`. | | -| `if-master-push` | Matches if the current branch is `master` and pipeline source is `push`. | | -| `if-master-schedule-2-hourly` | Matches if the current branch is `master` and pipeline runs on a 2-hourly schedule. | | -| `if-master-schedule-nightly` | Matches if the current branch is `master` and pipeline runs on a nightly schedule. | | +| `if-default-refs` | Matches if the pipeline is for `master`, `main`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. | +| `if-master-refs` | Matches if the current branch is `master` or `main`. | | +| `if-master-push` | Matches if the current branch is `master` or `main` and pipeline source is `push`. | | +| `if-master-schedule-2-hourly` | Matches if the current branch is `master` or `main` and pipeline runs on a 2-hourly schedule. | | +| `if-master-schedule-nightly` | Matches if the current branch is `master` or `main` and pipeline runs on a nightly schedule. | | | `if-auto-deploy-branches` | Matches if the current branch is an auto-deploy one. | | -| `if-master-or-tag` | Matches if the pipeline is for the `master` branch or for a tag. | | +| `if-master-or-tag` | Matches if the pipeline is for the `master` or `main` branch or for a tag. | | | `if-merge-request` | Matches if the pipeline is for a merge request. | | | `if-merge-request-title-as-if-foss` | Matches if the pipeline is for a merge request and the MR title includes "RUN AS-IF-FOSS". | | | `if-merge-request-title-update-caches` | Matches if the pipeline is for a merge request and the MR title includes "UPDATE CACHE". | | @@ -719,14 +718,14 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch | `if-security-schedule` | Matches if the pipeline is for a security scheduled pipeline. | | | `if-nightly-master-schedule` | Matches if the pipeline is for a `master` scheduled pipeline with `$NIGHTLY` set. | | | `if-dot-com-gitlab-org-schedule` | Limits jobs creation to scheduled pipelines for the `gitlab-org` group on GitLab.com. | | -| `if-dot-com-gitlab-org-master` | Limits jobs creation to the `master` branch for the `gitlab-org` group on GitLab.com. | | +| `if-dot-com-gitlab-org-master` | Limits jobs creation to the `master` or `main` branch for the `gitlab-org` group on GitLab.com. | | | `if-dot-com-gitlab-org-merge-request` | Limits jobs creation to merge requests for the `gitlab-org` group on GitLab.com. | | | `if-dot-com-gitlab-org-and-security-tag` | Limits job creation to tags for the `gitlab-org` and `gitlab-org/security` groups on GitLab.com. | | | `if-dot-com-gitlab-org-and-security-merge-request` | Limit jobs creation to merge requests for the `gitlab-org` and `gitlab-org/security` groups on GitLab.com. | | | `if-dot-com-gitlab-org-and-security-tag` | Limit jobs creation to tags for the `gitlab-org` and `gitlab-org/security` groups on GitLab.com. | | | `if-dot-com-ee-schedule` | Limits jobs to scheduled pipelines for the `gitlab-org/gitlab` project on GitLab.com. | | | `if-cache-credentials-schedule` | Limits jobs to scheduled pipelines with the `$CI_REPO_CACHE_CREDENTIALS` variable set. | | -| `if-rspec-fail-fast-disabled` | Limits jobs to pipelines with `$RSPEC_FAIL_FAST_ENABLED` variable not set to `"true"`. | | +| `if-rspec-fail-fast-disabled` | Limits jobs to pipelines with `$RSPEC_FAIL_FAST_ENABLED` CI/CD variable not set to `"true"`. | | | `if-rspec-fail-fast-skipped` | Matches if the pipeline is for a merge request and the MR title includes "SKIP RSPEC FAIL-FAST". | | | `if-security-pipeline-merge-result` | Matches if the pipeline is for a security merge request triggered by `@gitlab-release-tools-bot`. | | diff --git a/doc/development/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md index 79075157ce4..43acf5b7e3f 100644 --- a/doc/development/product_analytics/usage_ping.md +++ b/doc/development/product_analytics/usage_ping.md @@ -1,8 +1,8 @@ --- -redirect_to: '../usage_ping.md' +redirect_to: '../usage_ping/index.md' --- -This document was moved to [another location](../usage_ping.md). +This document was moved to [another location](../usage_ping/index.md). <!-- This redirect file can be deleted after April 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/prometheus.md b/doc/development/prometheus.md deleted file mode 100644 index 62f30871f54..00000000000 --- a/doc/development/prometheus.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -redirect_to: '../user/project/integrations/prometheus.md' ---- - -This document was moved to [another location](../user/project/integrations/prometheus.md). - -<!-- This redirect file can be deleted after February 1, 2021. --> -<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/query_performance.md b/doc/development/query_performance.md index 3cb1b10c417..87e26cf42df 100644 --- a/doc/development/query_performance.md +++ b/doc/development/query_performance.md @@ -21,11 +21,11 @@ When you are optimizing your SQL queries, there are two dimensions to pay attent | Queries in a migration | `100ms` | This is different than the total [migration time](database_review.md#timing-guidelines-for-migrations). | | Concurrent operations in a migration | `5min` | Concurrent operations do not block the database, but they block the GitLab update. This includes operations such as `add_concurrent_index` and `add_concurrent_foreign_key`. | | Background migrations | `1s` | | -| Usage Ping | `1s` | See the [usage ping docs](usage_ping.md#developing-and-testing-usage-ping) for more details. | +| Usage Ping | `1s` | See the [usage ping docs](usage_ping/index.md#developing-and-testing-usage-ping) for more details. | - When analyzing your query's performance, pay attention to if the time you are seeing is on a [cold or warm cache](#cold-and-warm-cache). These guidelines apply for both cache types. - When working with batched queries, change the range and batch size to see how it effects the query timing and caching. -- If an existing query is already underperforming, make an effort to improve it. If it is too complex or would stall development, create a follow-up so it can be addressed in a timely manner. You can always ask the database reviewer or maintainer for help and guidance. +- If an existing query is not performing well, make an effort to improve it. If it is too complex or would stall development, create a follow-up so it can be addressed in a timely manner. You can always ask the database reviewer or maintainer for help and guidance. ## Cold and warm cache diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md index 13bb39a4a6c..98b386497df 100644 --- a/doc/development/rake_tasks.md +++ b/doc/development/rake_tasks.md @@ -340,3 +340,7 @@ bundle exec rake gitlab:graphql:schema:dump ``` This uses GraphQL Ruby's built-in Rake tasks to generate files in both [IDL](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51) and JSON formats. + +### Update documentation and schema definitions + +The following command combines the intent of [Update GraphQL documentation and schema definitions](#update-graphql-documentation-and-schema-definitions) and [Update machine-readable schema files](#update-machine-readable-schema-files): diff --git a/doc/development/redis.md b/doc/development/redis.md index 9f90c5ee760..c7111db0cdc 100644 --- a/doc/development/redis.md +++ b/doc/development/redis.md @@ -120,14 +120,13 @@ This shows commands that have taken a long time and may be a performance concern. The -[fluent-plugin-redis-slowlog](https://gitlab.com/gitlab-org/fluent-plugin-redis-slowlog) -project is responsible for taking the slowlog entries from Redis and -passing to fluentd (and ultimately Elasticsearch). +[`fluent-plugin-redis-slowlog`](https://gitlab.com/gitlab-org/fluent-plugin-redis-slowlog) +project is responsible for taking the `slowlog` entries from Redis and +passing to Fluentd (and ultimately Elasticsearch). ## Analyzing the entire keyspace -The [Redis Keyspace -Analyzer](https://gitlab.com/gitlab-com/gl-infra/redis-keyspace-analyzer) +The [Redis Keyspace Analyzer](https://gitlab.com/gitlab-com/gl-infra/redis-keyspace-analyzer) project contains tools for dumping the full key list and memory usage of a Redis instance, and then analyzing those lists while eliminating potentially sensitive data from the results. It can be used to find the most frequent key patterns, or diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md index 41a7defbc26..e9c95a14236 100644 --- a/doc/development/secure_coding_guidelines.md +++ b/doc/development/secure_coding_guidelines.md @@ -195,7 +195,7 @@ Go's [`regexp`](https://golang.org/pkg/regexp/) package uses `re2` and isn't vul - [Rubular](https://rubular.com/) is a nice online tool to fiddle with Ruby Regexps. - [Runaway Regular Expressions](https://www.regular-expressions.info/catastrophic.html) - [The impact of regular expression denial of service (ReDoS) in practice: an empirical study at the ecosystem scale](https://people.cs.vt.edu/~davisjam/downloads/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf). This research paper discusses approaches to automatically detect ReDoS vulnerabilities. -- [Freezing the web: A study of redos vulnerabilities in JavaScript-based web servers](https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-staicu.pdf). Another research paper about detecting ReDoS vulnerabilities. +- [Freezing the web: A study of ReDoS vulnerabilities in JavaScript-based web servers](https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-staicu.pdf). Another research paper about detecting ReDoS vulnerabilities. ## Server Side Request Forgery (SSRF) diff --git a/doc/development/service_measurement.md b/doc/development/service_measurement.md index 91fb8248db4..895ac540838 100644 --- a/doc/development/service_measurement.md +++ b/doc/development/service_measurement.md @@ -75,7 +75,7 @@ To actually use it, you need to enable measuring for the desired service by enab ### Enabling measurement using feature flags In the following example, the `:gitlab_service_measuring_projects_import_service` -[feature flag](feature_flags/development.md#enabling-a-feature-flag-locally-in-development) is used to enable the measuring feature +[feature flag](feature_flags/index.md#enabling-a-feature-flag-locally-in-development) is used to enable the measuring feature for `Projects::ImportService`. From ChatOps: diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md index ce00934b35c..cff199c8b1d 100644 --- a/doc/development/sidekiq_style_guide.md +++ b/doc/development/sidekiq_style_guide.md @@ -588,7 +588,7 @@ the `.with_route` scope defined on all `Routable`s. ### Cron workers -The context is automatically cleared for workers in the Cronjob queue +The context is automatically cleared for workers in the cronjob queue (`include CronjobQueue`), even when scheduling them from requests. We do this to avoid incorrect metadata when other jobs are scheduled from the cron worker. diff --git a/doc/development/snowplow.md b/doc/development/snowplow.md index a56e85ba50d..f5689068654 100644 --- a/doc/development/snowplow.md +++ b/doc/development/snowplow.md @@ -11,7 +11,7 @@ This guide provides an overview of how Snowplow works, and implementation detail For more information about Product Intelligence, see: - [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) -- [Usage Ping Guide](usage_ping.md) +- [Usage Ping Guide](usage_ping/index.md) More useful links: @@ -358,6 +358,7 @@ There are several tools for developing and testing Snowplow Event 1. For frontend events, in the MR description section, add a screenshot of the event's relevant section using the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension. 1. For backend events, please use Snowplow Micro and add the output of the Snowplow Micro good events `GET http://localhost:9090/micro/good`. +1. Include a member of the Product Intelligence team as a reviewer of your MR. Mention `@gitlab-org/growth/product_intelligence/engineers` in your MR to request a review. ### Snowplow Analytics Debugger Chrome Extension @@ -484,9 +485,9 @@ For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.c ### `gitlab_standard` -We are currently working towards including the [`gitlab_standard` schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/) with every event. See [Standardize Snowplow Schema](https://gitlab.com/groups/gitlab-org/-/epics/5218) for details. +We are including the [`gitlab_standard` schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/) with every event. See [Standardize Snowplow Schema](https://gitlab.com/groups/gitlab-org/-/epics/5218) for details. -The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb) class represents this schema in the application. +The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb) class represents this schema in the application. | Field Name | Required | Type | Description | |----------------|---------------------|-----------------------|---------------------------------------------------------------------------------------------| diff --git a/doc/development/sql.md b/doc/development/sql.md index f68ca44efa8..8726c1331e8 100644 --- a/doc/development/sql.md +++ b/doc/development/sql.md @@ -12,13 +12,13 @@ either using ActiveRecord/Arel or raw SQL queries. ## Using LIKE Statements The most common way to search for data is using the `LIKE` statement. For -example, to get all issues with a title starting with "WIP:" you'd write the +example, to get all issues with a title starting with "Draft:" you'd write the following query: ```sql SELECT * FROM issues -WHERE title LIKE 'WIP:%'; +WHERE title LIKE 'Draft:%'; ``` On PostgreSQL the `LIKE` statement is case-sensitive. To perform a case-insensitive @@ -28,13 +28,13 @@ To handle this automatically you should use `LIKE` queries using Arel instead of raw SQL fragments, as Arel automatically uses `ILIKE` on PostgreSQL. ```ruby -Issue.where('title LIKE ?', 'WIP:%') +Issue.where('title LIKE ?', 'Draft:%') ``` You'd write this instead: ```ruby -Issue.where(Issue.arel_table[:title].matches('WIP:%')) +Issue.where(Issue.arel_table[:title].matches('Draft:%')) ``` Here `matches` generates the correct `LIKE` / `ILIKE` statement depending on the @@ -45,7 +45,7 @@ If you need to chain multiple `OR` conditions you can also do this using Arel: ```ruby table = Issue.arel_table -Issue.where(table[:title].matches('WIP:%').or(table[:foo].matches('WIP:%'))) +Issue.where(table[:title].matches('Draft:%').or(table[:foo].matches('Draft:%'))) ``` On PostgreSQL, this produces: @@ -53,7 +53,7 @@ On PostgreSQL, this produces: ```sql SELECT * FROM issues -WHERE (title ILIKE 'WIP:%' OR foo ILIKE 'WIP:%') +WHERE (title ILIKE 'Draft:%' OR foo ILIKE 'Draft:%') ``` ## LIKE & Indexes @@ -64,7 +64,7 @@ the start. For example, this will not use any indexes: ```sql SELECT * FROM issues -WHERE title ILIKE '%WIP:%'; +WHERE title ILIKE '%Draft:%'; ``` Because the value for `ILIKE` starts with a wildcard the database is not able to diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index 79ff46ae352..ee8401e08d4 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -168,7 +168,7 @@ can be used: ```ruby RSpec.describe API::Search, factory_default: :keep do - let_it_be(:namespace) { create_default(:namespace) } + let_it_be(:namespace) { create_default(:namespace).freeze } ``` Then every project we create uses this `namespace`, without us having to pass @@ -176,13 +176,17 @@ it as `namespace: namespace`. In order to make it work along with `let_it_be`, ` must be explicitly specified. That keeps the default factory for every example in a suite instead of recreating it for each example. +Objects created inside a `factory_default: :keep`, and using +`create_default` inside a `let_it_be` should be frozen to prevent accidental reliance +between test examples. + Maybe we don't need to create 208 different projects - we can create one and reuse it. In addition, we can see that only about 1/3 of the projects we create are ones we ask for (76/208). There is benefit in setting a default value for projects as well: ```ruby - let_it_be(:project) { create_default(:project) } + let_it_be(:project) { create_default(:project).freeze } ``` In this case, the `total time` and `top-level time` numbers match more closely: @@ -541,7 +545,7 @@ end ### Feature flags in tests -This section was moved to [developing with feature flags](../feature_flags/development.md). +This section was moved to [developing with feature flags](../feature_flags/index.md). ### Pristine test environments @@ -796,10 +800,11 @@ end ``` WARNING: -Only use simple values as input in the `where` block. Using procs, stateful +Only use simple values as input in the `where` block. Using +<!-- vale gitlab.Spelling = NO --> procs, stateful objects, FactoryBot-created objects, and similar items can lead to [unexpected results](https://github.com/tomykaira/rspec-parameterized/issues/8). - +<!-- vale gitlab.Spelling = YES --> ### Prometheus tests Prometheus metrics may be preserved from one test run to another. To ensure that metrics are @@ -981,6 +986,7 @@ GitLab uses [factory_bot](https://github.com/thoughtbot/factory_bot) as a test f See [issue #262624](https://gitlab.com/gitlab-org/gitlab/-/issues/262624) for further context. - Factories don't have to be limited to `ActiveRecord` objects. [See example](https://gitlab.com/gitlab-org/gitlab-foss/commit/0b8cefd3b2385a21cfed779bd659978c0402766d). +- Factories and their traits should produce valid objects that are [verified by specs](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/factories_spec.rb). ### Fixtures diff --git a/doc/development/testing_guide/end_to_end/best_practices.md b/doc/development/testing_guide/end_to_end/best_practices.md index a5a2d2a1113..2b4212a0172 100644 --- a/doc/development/testing_guide/end_to_end/best_practices.md +++ b/doc/development/testing_guide/end_to_end/best_practices.md @@ -309,10 +309,10 @@ This action can also unintentionally click other elements, altering the test sta # Clicking another element to blur an input def add_issue_to_epic(issue_url) find_element(:issue_actions_split_button).find('button', text: 'Add an issue').click - fill_element :add_issue_input, issue_url + fill_element(:add_issue_input, issue_url) # Clicking the title blurs the input - click_element :title - click_element :add_issue_button + click_element(:title) + click_element(:add_issue_button) end # Using native mouse click events in the case of a mask/overlay diff --git a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md index 1e7f528f6ff..6c504e6fa28 100644 --- a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md +++ b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md @@ -39,7 +39,7 @@ appear on the webpage, or the test to navigate away from the page entirely. Dynamic element validation is instituted when using ```ruby -click_element :my_element, Some::Page +click_element(:my_element, Some::Page) ``` ### Required Elements @@ -79,7 +79,7 @@ class MyPage < Page::Base end def open_layer - click_element :my_element, Layer::MyLayer + click_element(:my_element, Layer::MyLayer) end end @@ -109,7 +109,7 @@ Given the [source](#examples) ... ```ruby def open_layer - click_element :my_element, Layer::MyLayer + click_element(:my_element, Layer::MyLayer) end ``` diff --git a/doc/development/testing_guide/end_to_end/environment_selection.md b/doc/development/testing_guide/end_to_end/environment_selection.md index 7e34b6c265d..bcdf0e104dd 100644 --- a/doc/development/testing_guide/end_to_end/environment_selection.md +++ b/doc/development/testing_guide/end_to_end/environment_selection.md @@ -58,7 +58,7 @@ end If the test has a `before` or `after`, you must add the `only` metadata to the outer `RSpec.describe`. -If you want to run an `only: { :pipeline }` tagged test on your local GDK make sure either the `CI_PROJECT_NAME` environment variable is unset, or that the `CI_PROJECT_NAME` environment variable matches the specified pipeline in the `only: { :pipeline }` tag, or just delete the `only: { :pipeline }` tag. +If you want to run an `only: { :pipeline }` tagged test on your local GDK make sure either the `CI_PROJECT_NAME` CI/CD variable is unset, or that the `CI_PROJECT_NAME` variable matches the specified pipeline in the `only: { :pipeline }` tag, or just delete the `only: { :pipeline }` tag. ## Quarantining a test for a specific environment diff --git a/doc/development/testing_guide/end_to_end/feature_flags.md b/doc/development/testing_guide/end_to_end/feature_flags.md index 1bc33b79c7c..e3719393d41 100644 --- a/doc/development/testing_guide/end_to_end/feature_flags.md +++ b/doc/development/testing_guide/end_to_end/feature_flags.md @@ -18,8 +18,8 @@ Please be sure to include the tag `:requires_admin` so that the test can be skip where admin access is not available. WARNING: -You are strongly advised to [enable feature flags only for a group, project, user](../../feature_flags/development.md#feature-actors), -or [feature group](../../feature_flags/development.md#feature-groups). This makes it possible to +You are strongly advised to [enable feature flags only for a group, project, user](../../feature_flags/index.md#feature-actors), +or [feature group](../../feature_flags/index.md#feature-groups). This makes it possible to test a feature in a shared environment without affecting other users. For example, the code below would enable a feature flag named `:feature_flag_name` for the project diff --git a/doc/development/testing_guide/end_to_end/page_objects.md b/doc/development/testing_guide/end_to_end/page_objects.md index d9309f74e0e..b124ac430f6 100644 --- a/doc/development/testing_guide/end_to_end/page_objects.md +++ b/doc/development/testing_guide/end_to_end/page_objects.md @@ -201,7 +201,7 @@ We can select on that specific issue by matching on the Rails model. ```ruby class Page::Project::Issues::Index < Page::Base def has_issue?(issue) - has_element? :issue, issue_title: issue + has_element?(:issue, issue_title: issue) end end ``` diff --git a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md index b6293ec41b8..ea48a3aa8b8 100644 --- a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md +++ b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md @@ -151,7 +151,7 @@ To run the Monitor tests locally, against the GDK, please follow the preparation 1. The test setup deploys the app in a Kubernetes cluster, using the Auto DevOps deployment strategy. To enable Auto DevOps in GDK, follow the [associated setup](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/index.md#setup) instructions. If you have problems, review the [troubleshooting guide](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/tips_and_troubleshooting.md) or reach out to the `#gdk` channel in the internal GitLab Slack. 1. Do [secure your GitLab instance](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/index.md#secure-your-gitlab-instance) since it is now publicly accessible on `https://[YOUR-PORT].qa-tunnel.gitlab.info`. -1. Install the Kubernetes command line tool known as `kubectl`. Use the [official installation instructions](https://kubernetes.io/docs/tasks/tools/install-kubectl/). +1. Install the Kubernetes command line tool known as `kubectl`. Use the [official installation instructions](https://kubernetes.io/docs/tasks/tools/). You might see NGINX issues when you run `gdk start` or `gdk restart`. In that case, run `sft login` to revalidate your credentials and regain access the QA Tunnel. diff --git a/doc/development/testing_guide/end_to_end/style_guide.md b/doc/development/testing_guide/end_to_end/style_guide.md index ac4d26df794..f9c13d5dd67 100644 --- a/doc/development/testing_guide/end_to_end/style_guide.md +++ b/doc/development/testing_guide/end_to_end/style_guide.md @@ -19,7 +19,7 @@ E.g.: ```ruby def click_ci_cd_pipelines within_sidebar do - click_element :link_pipelines + click_element(:link_pipelines) end end ``` diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index 73fce3a38d7..9facca10142 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -126,7 +126,7 @@ It does not make sense to test our `getFahrenheit` function because underneath i Let's take a short look into Vue land. Vue is a critical part of the GitLab JavaScript codebase. When writing specs for Vue components, a common gotcha is to actually end up testing Vue provided functionality, because it appears to be the easiest thing to test. Here's an example taken from our codebase. ```javascript -// Component +// Component script { computed: { hasMetricTypes() { @@ -135,27 +135,46 @@ Let's take a short look into Vue land. Vue is a critical part of the GitLab Java } ``` -and here's the corresponding spec +```html +<!-- Component template --> +<template> + <gl-dropdown v-if="hasMetricTypes"> + <!-- Dropdown content --> + </gl-dropdown> +</template> +``` + +Testing the `hasMetricTypes` computed prop would seem like a given here. But to test if the computed property is returning the length of `metricTypes`, is testing the Vue library itself. There is no value in this, besides it adding to the test suite. It's better to test a component in the way the user interacts with it: checking the rendered template. ```javascript - describe('computed', () => { - describe('hasMetricTypes', () => { - it('returns true if metricTypes exist', () => { - factory({ metricTypes }); - expect(wrapper.vm.hasMetricTypes).toBe(2); - }); - - it('returns true if no metricTypes exist', () => { - factory(); - expect(wrapper.vm.hasMetricTypes).toBe(0); - }); +// Bad +describe('computed', () => { + describe('hasMetricTypes', () => { + it('returns true if metricTypes exist', () => { + factory({ metricTypes }); + expect(wrapper.vm.hasMetricTypes).toBe(2); + }); + + it('returns true if no metricTypes exist', () => { + factory(); + expect(wrapper.vm.hasMetricTypes).toBe(0); }); + }); }); -``` -Testing the `hasMetricTypes` computed prop would seem like a given, but to test if the computed property is returning the length of `metricTypes`, is testing the Vue library itself. There is no value in this, besides it adding to the test suite. Better is to test it in the way the user interacts with it. Probably through the template. +// Good +it('displays a dropdown if metricTypes exist', () => { + factory({ metricTypes }); + expect(wrapper.findComponent(GlDropdown).exists()).toBe(true); +}); + +it('does not display a dropdown if no metricTypes exist', () => { + factory(); + expect(wrapper.findComponent(GlDropdown).exists()).toBe(false); +}); +``` -Keep an eye out for these kinds of tests, as they just make updating logic more fragile and tedious than it needs to be. This is also true for other libraries. +Keep an eye out for these kinds of tests, as they just make updating logic more fragile and tedious than it needs to be. This is also true for other libraries. A rule of thumb here is: if you are checking a `wrapper.vm` property, you should probably stop and rethink the test to check the rendered template instead. Some more examples can be found in the [Frontend unit tests section](testing_levels.md#frontend-unit-tests) @@ -193,7 +212,7 @@ When it comes to querying DOM elements in your tests, it is best to uniquely and the element. Preferentially, this is done by targeting what the user actually sees using [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro/). -When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/dom-testing-library/api-queries/#byrole) +When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/queries/byrole/) as these enforce accessibility best practices as well. The examples below demonstrate the order of preference. When writing Vue component unit tests, it can be wise to query children by component, so that the unit test can focus on comprehensive value coverage @@ -539,21 +558,6 @@ When looking at this initially you'd suspect that the component is setup before This is however not entirely true as the `destroy` method does not remove everything which has been mutated on the `wrapper` object. For functional components, destroy only removes the rendered DOM elements from the document. -In order to ensure that a clean wrapper object and DOM are being used in each test, the breakdown of the component should rather be performed as follows: - -```javascript - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); -``` - -<!-- vale gitlab.Spelling = NO --> - -See also the [Vue Test Utils documentation on `destroy`](https://vue-test-utils.vuejs.org/api/wrapper/#destroy). - -<!-- vale gitlab.Spelling = YES --> - ### Jest best practices > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34209) in GitLab 13.2. @@ -687,7 +691,7 @@ Similarly, if you really need to use the real `Date` class, then you can import ```javascript import { useRealDate } from 'helpers/fake_date'; -// NOTE: `useRealDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.). +// NOTE: `useRealDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.). describe('with real date', () => { useRealDate(); }); @@ -1034,7 +1038,7 @@ describe "Admin::AbuseReports", :js do end ``` -### Jest test timeout due to async imports +### Jest test timeout due to asynchronous imports If a module asynchronously imports some other modules at runtime, these modules must be transpiled by the Jest loaders at runtime. It's possible that this can cause [Jest to timeout](https://gitlab.com/gitlab-org/gitlab/-/issues/280809). @@ -1183,6 +1187,95 @@ You can download any older version of Firefox from the releases FTP server, <htt 1. Open up a terminal and run `/Applications/Firefox_Old.app/Contents/MacOS/firefox-bin -profilemanager` to create a new profile specific to that Firefox version. 1. Once the profile has been created, quit the app, and run it again like normal. You now have a working older Firefox version. +## Snapshots + +By now you've probably heard of [Jest snapshot tests](https://jestjs.io/docs/en/snapshot-testing) and why they are useful for various reasons. +To use them within GitLab, there are a few guidelines that should be highlighted: + +- Treat snapshots as code +- Don't think of a snapshot file as a Blackbox +- Care for the output of the snapshot, otherwise, it's not providing any real value. This will usually involve reading the generated snapshot file as you would read any other piece of code + +Think of a snapshot test as a simple way to store a raw `String` representation of what you've put into the item being tested. This can be used to evaluate changes in a component, a store, a complex piece of generated output, etc. You can see more in the list below for some recommended `Do's and Don'ts`. +While snapshot tests can be a very powerful tool. They are meant to supplement, not to replace unit tests. + +Jest provides a great set of docs on [best practices](https://jestjs.io/docs/en/snapshot-testing#best-practices) that we should keep in mind when creating snapshots. + +### How does a snapshot work? + +A snapshot is purely a stringified version of what you ask to be tested on the lefthand side of the function call. This means any kind of changes you make to the formatting of the string has an impact on the outcome. This process is done by leveraging serializers for an automatic transform step. For Vue this is already taken care of by leveraging the `vue-jest` package, which offers the proper serializer. + +Should the outcome of your spec be different from what is in the generated snapshot file, you'll be notified about it by a failing test in your test suite. + +Find all the details in Jests official documentation [https://jestjs.io/docs/en/snapshot-testing](https://jestjs.io/docs/en/snapshot-testing) + +### How to take a snapshot + +```javascript +it('makes the name look pretty', () => { + expect(prettifyName('Homer Simpson')).toMatchSnapshot() +}) +``` + +When this test runs the first time a fresh `.snap` file will be created. It will look something like this: + +```txt +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`makes the name look pretty`] = ` +Sir Homer Simpson the Third +` +``` + +Now, every time you call this test, the new snapshot will be evaluated against the previously created version. This should highlight the fact that it's important to understand the content of your snapshot file and treat it with care. Snapshots will lose their value if the output of the snapshot is too big or complex to read, this means keeping snapshots isolated to human-readable items that can be either evaluated in a merge request review or are guaranteed to never change. +The same can be done for `wrappers` or `elements` + +```javascript +it('renders the component correctly', () => { + expect(wrapper).toMatchSnapshot() + expect(wrapper.element).toMatchSnapshot(); +}) +``` + +The above test will create two snapshots, what's important is to decide which of the snapshots provide more value for the codebase safety i.e. if one of these snapshots changes, does that highlight a possible un-wanted break in the codebase? This can help catch unexpected changes if something in an underlying dependency changes without our knowledge. + +### Pros and Cons + +**Pros** + +- Speed up the creation of unit tests +- Easy to maintain +- Provides a good safety net to protect against accidental breakage of important HTML structures + +**Cons** + +- Is not a catch-all solution that replaces the work of integration or unit tests +- No meaningful assertions or expectations within snapshots +- When carelessly used with [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui) it can create fragility in tests when the underlying library changes the HTML of a component we are testing + +A good guideline to follow: the more complex the component you may want to steer away from just snapshot testing. But that's not to say you can't still snapshot test and test your component as normal. + +### When to use + +**Use snapshots when** + +- to capture a components rendered output +- to fully or partially match templates +- to match readable data structures +- to verify correctly composed native HTML elements +- as a safety net for critical structures so others don't break it by accident +- Template heavy component +- Not a lot of logic in the component +- Composed of native HTML elements + +### When not to use + +**Don't use snapshots when** + +- To capture large data structures just to have something +- To just have some kind of test written +- To capture highly volatile ui elements without stubbing them (Think of GitLab UI version updates) + --- [Return to Testing documentation](index.md) diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md index f1c74f990cb..c4194be23a4 100644 --- a/doc/development/testing_guide/review_apps.md +++ b/doc/development/testing_guide/review_apps.md @@ -109,10 +109,10 @@ subgraph "CNG-mirror pipeline" ### Auto-stopping of Review Apps Review Apps are automatically stopped 2 days after the last deployment thanks to -the [Environment auto-stop](../../ci/environments/index.md#environments-auto-stop) feature. +the [Environment auto-stop](../../ci/environments/index.md#stop-an-environment-after-a-certain-time-period) feature. If you need your Review App to stay up for a longer time, you can -[pin its environment](../../ci/environments/index.md#auto-stop-example) or retry the +[pin its environment](../../ci/environments/index.md#override-a-deployments-scheduled-stop-time) or retry the `review-deploy` job to update the "latest deployed at" time. The `review-cleanup` job that automatically runs in scheduled diff --git a/doc/development/transient/prevention-patterns.md b/doc/development/transient/prevention-patterns.md index 4c1e4d373e7..2bfd188fd43 100644 --- a/doc/development/transient/prevention-patterns.md +++ b/doc/development/transient/prevention-patterns.md @@ -10,7 +10,7 @@ This page will cover architectural patterns and tips for developers to follow to ## Common root causes -We've noticed a few root causes that come up frequently when addressing transient bugs. +We've noticed a few root causes that come up frequently when addressing transient bugs. - Needs better state management in the backend or frontend. - Frontend code needs improvements. diff --git a/doc/development/usage_ping.md b/doc/development/usage_ping.md index 3618d18b1bb..b8f08caaebd 100644 --- a/doc/development/usage_ping.md +++ b/doc/development/usage_ping.md @@ -1,1188 +1,7 @@ --- -stage: Growth -group: Product Intelligence -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 +redirect_to: 'usage_ping/index.md' --- -# Usage Ping Guide - -> Introduced in GitLab Ultimate 11.2, more statistics. - -This guide describes Usage Ping's purpose and how it's implemented. - -For more information about Product Intelligence, see: - -- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) -- [Snowplow Guide](snowplow.md) - -More useful links: - -- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/) -- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) -- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) -- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) - -## What is Usage Ping? - -- GitLab sends a weekly payload containing usage data to GitLab Inc. Usage Ping provides high-level data to help our product, support, and sales teams. It does not send any project names, usernames, or any other specific data. The information from the usage ping is not anonymous, it is linked to the hostname of the instance. Sending usage ping is optional, and any instance can disable analytics. -- The usage data is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features within the product. In addition to counts, other facts - that help us classify and understand GitLab installations are collected. -- Usage ping is important to GitLab as we use it to calculate our Stage Monthly Active Users (SMAU) which helps us measure the success of our stages and features. -- While usage ping is enabled, GitLab gathers data from the other instances and can show usage statistics of your instance to your users. - -### Why should we enable Usage Ping? - -- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions. -- As a benefit of having the usage ping active, GitLab lets you analyze the users’ activities over time of your GitLab installation. -- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring. -- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value) -- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization? -- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes. -- Usage Ping is enabled by default. To disable it, see [Disable Usage Ping](#disable-usage-ping). - -### Limitations - -- Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events. -- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Usage Ping to track aggregated backend events on self-managed. - -## Usage Ping payload - -You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload: - -1. Navigate to **Admin Area > Settings > Metrics and profiling**. -1. Expand the **Usage statistics** section. -1. Click the **Preview payload** button. - -For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload). - -## Disable Usage Ping - -To disable Usage Ping in the GitLab UI, go to the **Settings** page of your administration panel and uncheck the **Usage Ping** checkbox. - -To disable Usage Ping and prevent it from being configured in the future through the administration panel, Omnibus installs can set the following in [`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options): - -```ruby -gitlab_rails['usage_ping_enabled'] = false -``` - -Source installations can set the following in `gitlab.yml`: - -```yaml -production: &base - # ... - gitlab: - # ... - usage_ping_enabled: false -``` - -## Usage Ping request flow - -The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, the GitLab S3 Bucket, the GitLab Snowflake Data Warehouse, and Sisense: - -```mermaid -sequenceDiagram - participant GitLab Instance - participant Versions Application - participant Licenses Application - participant Salesforce - participant S3 Bucket - participant Snowflake DW - participant Sisense Dashboards - GitLab Instance->>Versions Application: Send Usage Ping - loop Process usage data - Versions Application->>Versions Application: Parse usage data - Versions Application->>Versions Application: Write to database - Versions Application->>Versions Application: Update license ping time - end - loop Process data for Salesforce - Versions Application-xLicenses Application: Request Zuora subscription id - Licenses Application-xVersions Application: Zuora subscription id - Versions Application-xSalesforce: Request Zuora account id by Zuora subscription id - Salesforce-xVersions Application: Zuora account id - Versions Application-xSalesforce: Usage data for the Zuora account - end - Versions Application->>S3 Bucket: Export Versions database - S3 Bucket->>Snowflake DW: Import data - Snowflake DW->>Snowflake DW: Transform data using dbt - Snowflake DW->>Sisense Dashboards: Data available for querying - Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index) -``` - -## How Usage Ping works - -1. The Usage Ping [cron job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30) is set in Sidekiq to run weekly. -1. When the cron job runs, it calls [`Gitlab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22). -1. `Gitlab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls. -1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `Gitlab::UsageData.to_json`. -1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20) - If a firewall exception is needed, the required URL depends on several things. If - the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`, - the required URL is <https://version.gitlab.com/>. - -## Usage Ping Metric Life cycle - -### 1. New metrics addition - -Please follow the [Implementing Usage Ping](#implementing-usage-ping) guide. - -### 2. Existing metric change - -Because we do not control when customers update their self-managed instances of GitLab, -we **STRONGLY DISCOURAGE** changes to the logic used to calculate any metric. -Any such changes lead to inconsistent reports from multiple GitLab instances. -If there is a problem with an existing metric, it's best to deprecate the existing metric, -and use it, side by side, with the desired new metric. - -Example: -Consider following change. Before GitLab 12.6, the `example_metric` was implemented as: - -```ruby -{ - ... - example_metric: distinct_count(Project, :creator_id) -} -``` - -For GitLab 12.6, the metric was changed to filter out archived projects: - -```ruby -{ - ... - example_metric: distinct_count(Project.non_archived, :creator_id) -} -``` - -In this scenario all instances running up to GitLab 12.5 continue to report `example_metric`, -including all archived projects, while all instances running GitLab 12.6 and higher filters -out such projects. As Usage Ping data is collected from all reporting instances, the -resulting dataset includes mixed data, which distorts any following business analysis. - -The correct approach is to add a new metric for GitLab 12.6 release with updated logic: - -```ruby -{ - ... - example_metric_without_archived: distinct_count(Project.non_archived, :creator_id) -} -``` - -and update existing business analysis artefacts to use `example_metric_without_archived` instead of `example_metric` - -### 3. Metrics deprecation and removal - -The process for deprecating and removing metrics is currently under development. For -more information, see the following [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284637). - -## Implementing Usage Ping - -Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event -happened over time, such as how many CI pipelines have run. They are monotonic and always trend up. -Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no -general guidelines around how to collect those, due to the individual nature of that data. - -There are several types of counters which are all found in `usage_data.rb`: - -- **Ordinary Batch Counters:** Simple count of a given ActiveRecord_Relation -- **Distinct Batch Counters:** Distinct count of a given ActiveRecord_Relation in a given column -- **Sum Batch Counters:** Sum the values of a given ActiveRecord_Relation in a given column -- **Alternative Counters:** Used for settings and configurations -- **Redis Counters:** Used for in-memory counts. - -NOTE: -Only use the provided counter methods. Each counter method contains a built in fail safe to isolate each counter to avoid breaking the entire Usage Ping. - -### Why batch counting - -For large tables, PostgreSQL can take a long time to count rows due to MVCC [(Multi-version Concurrency Control)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control). Batch counting is a counting method where a single large query is broken into multiple smaller queries. For example, instead of a single query querying 1,000,000 records, with batch counting, you can execute 100 queries of 10,000 records each. Batch counting is useful for avoiding database timeouts as each batch query is significantly shorter than one single long running query. - -For GitLab.com, there are extremely large tables with 15 second query timeouts, so we use batch counting to avoid encountering timeouts. Here are the sizes of some GitLab.com tables: - -| Table | Row counts in millions | -|------------------------------|------------------------| -| `merge_request_diff_commits` | 2280 | -| `ci_build_trace_sections` | 1764 | -| `merge_request_diff_files` | 1082 | -| `events` | 514 | - -We have several batch counting methods available: - -- `Ordinary Batch Counters` -- `Distinct Batch Counters` -- `Sum Batch Counters` -- `Estimated Batch Counters` - -Batch counting requires indexes on columns to calculate max, min, and range queries. In some cases, -you may need to add a specialized index on the columns involved in a counter. - -### Ordinary Batch Counters - -Handles `ActiveRecord::StatementInvalid` error - -Simple count of a given ActiveRecord_Relation, does a non-distinct batch count, smartly reduces batch_size and handles errors. - -Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)` - -Arguments: - -- `relation` the ActiveRecord_Relation to perform the count -- `column` the column to perform the count on, by default is the primary key -- `batch`: default `true` to use batch counting -- `start`: custom start of the batch counting to avoid complex min calculations -- `end`: custom end of the batch counting to avoid complex min calculations - -Examples: - -```ruby -count(User.active) -count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) -count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id)) -``` - -### Distinct Batch Counters - -Handles `ActiveRecord::StatementInvalid` error - -Distinct count of a given ActiveRecord_Relation on given column, a distinct batch count, smartly reduces batch_size and handles errors. - -Method: `distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)` - -Arguments: - -- `relation` the ActiveRecord_Relation to perform the count -- `column` the column to perform the distinct count, by default is the primary key -- `batch`: default `true` to use batch counting -- `batch_size`: if none set it uses default value 10000 from `Gitlab::Database::BatchCounter` -- `start`: custom start of the batch counting to avoid complex min calculations -- `end`: custom end of the batch counting to avoid complex min calculations - -WARNING: -Counting over non-unique columns can lead to performance issues. Take a look at the [iterating tables in batches](iterating_tables_in_batches.md) guide for more details. - -Examples: - -```ruby -distinct_count(::Project, :creator_id) -distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) -distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') -``` - -### Sum Batch Counters - -Handles `ActiveRecord::StatementInvalid` error - -Sum the values of a given ActiveRecord_Relation on given column and handles errors. - -Method: `sum(relation, column, batch_size: nil, start: nil, finish: nil)` - -Arguments: - -- `relation` the ActiveRecord_Relation to perform the operation -- `column` the column to sum on -- `batch_size`: if none set it uses default value 1000 from `Gitlab::Database::BatchCounter` -- `start`: custom start of the batch counting to avoid complex min calculations -- `end`: custom end of the batch counting to avoid complex min calculations - -Examples: - -```ruby -sum(JiraImportState.finished, :imported_issues_count) -``` - -### Grouping & Batch Operations - -The `count`, `distinct_count`, and `sum` batch counters can accept an `ActiveRecord::Relation` -object, which groups by a specified column. With a grouped relation, the methods do batch counting, -handle errors, and returns a hash table of key-value pairs. - -Examples: - -```ruby -count(Namespace.group(:type)) -# returns => {nil=>179, "Group"=>54} - -distinct_count(Project.group(:visibility_level), :creator_id) -# returns => {0=>1, 10=>1, 20=>11} - -sum(Issue.group(:state_id), :weight)) -# returns => {1=>3542, 2=>6820} -``` - -### Estimated Batch Counters - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233) in GitLab 13.7. - -Estimated batch counter functionality handles `ActiveRecord::StatementInvalid` errors -when used through the provided `estimate_batch_distinct_count` method. -Errors return a value of `-1`. - -WARNING: -This functionality estimates a distinct count of a specific ActiveRecord_Relation in a given column, -which uses the [HyperLogLog](http://algo.inria.fr/flajolet/Publications/FlFuGaMe07.pdf) algorithm. -As the HyperLogLog algorithm is probabilistic, the **results always include error**. -The highest encountered error rate is 4.9%. - -When correctly used, the `estimate_batch_distinct_count` method enables efficient counting over -columns that contain non-unique values, which can not be assured by other counters. - -Method: [`estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/utils/usage_data.rb#L63) - -The method includes the following arguments: - -- `relation`: The ActiveRecord_Relation to perform the count. -- `column`: The column to perform the distinct count. The default is the primary key. -- `batch_size`: The default is 10,000, from `Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE`. -- `start`: The custom start of the batch count, to avoid complex minimum calculations. -- `finish`: The custom end of the batch count to avoid complex maximum calculations. - -The method includes the following prerequisites: - -1. The supplied `relation` must include the primary key defined as the numeric column. - For example: `id bigint NOT NULL`. -1. The `estimate_batch_distinct_count` can handle a joined relation. To use its ability to - count non-unique columns, the joined relation **must NOT** have a one-to-many relationship, - such as `has_many :boards`. -1. Both `start` and `finish` arguments should always represent primary key relationship values, - even if the estimated count refers to another column, for example: - - ```ruby - estimate_batch_distinct_count(::Note, :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id)) - ``` - -Examples: - -1. Simple execution of estimated batch counter, with only relation provided, - returned value represents estimated number of unique values in `id` column - (which is the primary key) of `Project` relation: - - ```ruby - estimate_batch_distinct_count(::Project) - ``` - -1. Execution of estimated batch counter, where provided relation has applied - additional filter (`.where(time_period)`), number of unique values estimated - in custom column (`:author_id`), and parameters: `start` and `finish` together - apply boundaries that defines range of provided relation to analyze: - - ```ruby - estimate_batch_distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id)) - ``` - -1. Execution of estimated batch counter with joined relation (`joins(:cluster)`), - for a custom column (`'clusters.user_id'`): - - ```ruby - estimate_batch_distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') - ``` - -When instrumenting metric with usage of estimated batch counter please add -`_estimated` suffix to its name, for example: - -```ruby - "counts": { - "ci_builds_estimated": estimate_batch_distinct_count(Ci::Build), - ... -``` - -### Redis Counters - -Handles `::Redis::CommandError` and `Gitlab::UsageDataCounters::BaseCounter::UnknownEvent` -returns -1 when a block is sent or hash with all values -1 when a `counter(Gitlab::UsageDataCounters)` is sent -different behavior due to 2 different implementations of Redis counter - -Method: `redis_usage_data(counter, &block)` - -Arguments: - -- `counter`: a counter from `Gitlab::UsageDataCounters`, that has `fallback_totals` method implemented -- or a `block`: which is evaluated - -#### Ordinary Redis Counters - -Examples of implementation: - -- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb) -- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb) - -##### UsageData API Tracking - -<!-- There's nearly identical content in `##### Adding new events`. If you fix errors here, you may need to fix the same errors in the other location. --> - -1. Track event using `UsageData` API - - Increment event count using ordinary Redis counter, for given event name. - - Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. - - API requests are protected by checking for a valid CSRF token. - - To be able to increment the values, the related feature `usage_data_<event_name>` should be enabled. - - ```plaintext - POST /usage_data/increment_counter - ``` - - | Attribute | Type | Required | Description | - | :-------- | :--- | :------- | :---------- | - | `event` | string | yes | The event name it should be tracked | - - Response - - - `200` if event was tracked - - `400 Bad request` if event parameter is missing - - `401 Unauthorized` if user is not authenticated - - `403 Forbidden` for invalid CSRF token provided - -1. Track events using JavaScript/Vue API helper which calls the API above - - Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled to be able to track events - - ```javascript - import api from '~/api'; - - api.trackRedisCounterEvent('my_already_defined_event_name'), - ``` - -#### Redis HLL Counters - -WARNING: -HyperLogLog (HLL) is a probabilistic algorithm and its **results always includes some small error**. According to [Redis documentation](https://redis.io/commands/pfcount), data from -used HLL implementation is "approximated with a standard error of 0.81%". - -With `Gitlab::UsageDataCounters::HLLRedisCounter` we have available data structures used to count unique values. - -Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PFCOUNT](https://redis.io/commands/pfcount). - -##### Adding new events - -1. Define events in [`known_events`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/). - - Example event: - - ```yaml - - name: i_compliance_credential_inventory - category: compliance - redis_slot: compliance - expiry: 42 # 6 weeks - aggregation: weekly - ``` - - Keys: - - - `name`: unique event name. - - Name format `<prefix>_<redis_slot>_name`. - - Use one of the following prefixes for the event's name: - - - `g_` for group, as an event which is tracked for group. - - `p_` for project, as an event which is tracked for project. - - `i_` for instance, as an event which is tracked for instance. - - `a_` for events encompassing all `g_`, `p_`, `i_`. - - `o_` for other. - - Consider including in the event's name the Redis slot to be able to count totals for a specific category. - - Example names: `i_compliance_credential_inventory`, `g_analytics_contribution`. - - - `category`: event category. Used for getting total counts for events in a category, for easier - access to a group of events. - - `redis_slot`: optional Redis slot; default value: event name. Used if needed to calculate totals - for a group of metrics. Ensure keys are in the same slot. For example: - `i_compliance_credential_inventory` with `redis_slot: 'compliance'` builds Redis key - `i_{compliance}_credential_inventory-2020-34`. If `redis_slot` is not defined the Redis key will - be `{i_compliance_credential_inventory}-2020-34`. - - `expiry`: expiry time in days. Default: 29 days for daily aggregation and 6 weeks for weekly - aggregation. - - `aggregation`: may be set to a `:daily` or `:weekly` key. Defines how counting data is stored in Redis. - Aggregation on a `daily` basis does not pull more fine grained data. - - `feature_flag`: optional `default_enabled: :yaml`. If no feature flag is set then the tracking is enabled. For details, see our [GitLab internal Feature flags](feature_flags/) documentation. The feature flags are owned by the group adding the event tracking. - -Use one of the following methods to track events: - -1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, if: nil)`. - - Arguments: - - - `controller_actions`: controller actions we want to track. - - `name`: event name. - - `if`: optional custom conditions, using the same format as with Rails callbacks. - - Example usage: - - ```ruby - # controller - class ProjectsController < Projects::ApplicationController - include RedisTracking - - skip_before_action :authenticate_user!, only: :show - track_redis_hll_event :index, :show, name: 'g_compliance_example_feature_visitors' - - def index - render html: 'index' - end - - def new - render html: 'new' - end - - def show - render html: 'show' - end - end - ``` - -1. Track event in API using `increment_unique_values(event_name, values)` helper method. - - To be able to track the event, Usage Ping must be enabled and the event feature `usage_data_<event_name>` must be enabled. - - Arguments: - - - `event_name`: event name. - - `values`: values counted, one value or array of values. - - Example usage: - - ```ruby - get ':id/registry/repositories' do - repositories = ContainerRepositoriesFinder.new( - user: current_user, subject: user_group - ).execute - - increment_unique_values('i_list_repositories', current_user.id) - - present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count] - end - ``` - -1. Track event using `track_usage_event(event_name, values) in services and GraphQL - - Increment unique values count using Redis HLL, for given event name. - - Example: - - [Track usage event for incident created in service](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.8.3-ee/app/services/issues/update_service.rb#L66) - - [Track usage event for incident created in GraphQL](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.8.3-ee/app/graphql/mutations/alert_management/update_alert_status.rb#L16) - - ```ruby - track_usage_event(:incident_management_incident_created, current_user.id) - ``` - -<!-- There's nearly identical content in `##### UsageData API Tracking`. If you find / fix errors here, you may need to fix errors in that section too. --> - -1. Track event using `UsageData` API - - Increment unique users count using Redis HLL, for given event name. - - Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. - - API requests are protected by checking for a valid CSRF token. - - To increment the values, the related feature `usage_data_<event_name>` should be - set to `default_enabled: true`. For more information, see - [Feature flags in development of GitLab](feature_flags/index.md). - - ```plaintext - POST /usage_data/increment_unique_users - ``` - - | Attribute | Type | Required | Description | - | :-------- | :--- | :------- | :---------- | - | `event` | string | yes | The event name it should be tracked | - - Response - - Return 200 if tracking failed for any reason. - - - `200` if event was tracked or any errors - - `400 Bad request` if event parameter is missing - - `401 Unauthorized` if user is not authenticated - - `403 Forbidden` for invalid CSRF token provided - -1. Track events using JavaScript/Vue API helper which calls the API above - - Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/): - - Usage Data API is behind `usage_data_api` feature flag which, as of GitLab 13.7, is - now set to `default_enabled: true`. - - Each event tracked using Usage Data API is behind a feature flag `usage_data_#{event_name}` which should be `default_enabled: true` - - ```javascript - import api from '~/api'; - - api.trackRedisHllUserEvent('my_already_defined_event_name'), - ``` - -1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date:, context: '')`. - - Arguments: - - - `event_names`: the list of event names. - - `start_date`: start date of the period for which we want to get event data. - - `end_date`: end date of the period for which we want to get event data. - - `context`: context of the event. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`. - -1. Testing tracking and getting unique events - -Trigger events in rails console by using `track_event` method - - ```ruby - Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: 1) - Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: [2, 3]) - ``` - -Next, get the unique events for the current week. - - ```ruby - # Get unique events for metric for current_week - Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_audit_events', - start_date: Date.current.beginning_of_week, end_date: Date.current.next_week) - ``` - -##### Recommendations - -We have the following recommendations for [Adding new events](#adding-new-events): - -- Event aggregation: weekly. -- Key expiry time: - - Daily: 29 days. - - Weekly: 42 days. -- When adding new metrics, use a [feature flag](../operations/feature_flags.md) to control the impact. -- For feature flags triggered by another service, set `default_enabled: false`, - - Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change - -##### Enable/Disable Redis HLL tracking - -Events are tracked behind [feature flags](feature_flags/index.md) due to concerns for Redis performance and scalability. - -For a full list of events and corresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files. - -To enable or disable tracking for specific event within <https://gitlab.com> or <https://about.staging.gitlab.com>, run commands such as the following to -[enable or disable the corresponding feature](feature_flags/index.md). - -```shell -/chatops run feature set <feature_name> true -/chatops run feature set <feature_name> false -``` - -##### Known events are added automatically in usage data payload - -All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209). -For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable: - -- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events. -- `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#adding-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#adding-new-events) events. - -Redis HLL implementation calculates automatic total metrics, if there are more than one metric for the same category, aggregation and Redis slot. - -- `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric. -- `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric. - -Example of `redis_hll_counters` data: - -```ruby -{:redis_hll_counters=> - {"compliance"=> - {"g_compliance_dashboard_weekly"=>0, - "g_compliance_dashboard_monthly"=>0, - "g_compliance_audit_events_weekly"=>0, - "g_compliance_audit_events_monthly"=>0, - "compliance_total_unique_counts_weekly"=>0, - "compliance_total_unique_counts_monthly"=>0}, - "analytics"=> - {"g_analytics_contribution_weekly"=>0, - "g_analytics_contribution_monthly"=>0, - "g_analytics_insights_weekly"=>0, - "g_analytics_insights_monthly"=>0, - "analytics_total_unique_counts_weekly"=>0, - "analytics_total_unique_counts_monthly"=>0}, - "ide_edit"=> - {"g_edit_by_web_ide_weekly"=>0, - "g_edit_by_web_ide_monthly"=>0, - "g_edit_by_sfe_weekly"=>0, - "g_edit_by_sfe_monthly"=>0, - "ide_edit_total_unique_counts_weekly"=>0, - "ide_edit_total_unique_counts_monthly"=>0}, - "search"=> - {"i_search_total_weekly"=>0, "i_search_total_monthly"=>0, "i_search_advanced_weekly"=>0, "i_search_advanced_monthly"=>0, "i_search_paid_weekly"=>0, "i_search_paid_monthly"=>0, "search_total_unique_counts_weekly"=>0, "search_total_unique_counts_monthly"=>0}, - "source_code"=>{"wiki_action_weekly"=>0, "wiki_action_monthly"=>0} - } -``` - -Example usage: - -```ruby -# Redis Counters -redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter) -redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] } - -# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml - -# Tracking events -Gitlab::UsageDataCounters::HLLRedisCounter.track_event('expand_vulnerabilities', values: visitor_id) - -# Get unique events for metric -redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'expand_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) } -``` - -### Alternative Counters - -Handles `StandardError` and fallbacks into -1 this way not all measures fail if we encounter one exception. -Mainly used for settings and configurations. - -Method: `alt_usage_data(value = nil, fallback: -1, &block)` - -Arguments: - -- `value`: a simple static value in which case the value is simply returned. -- or a `block`: which is evaluated -- `fallback: -1`: the common value used for any metrics that are failing. - -Example of usage: - -```ruby -alt_usage_data { Gitlab::VERSION } -alt_usage_data { Gitlab::CurrentSettings.uuid } -alt_usage_data(999) -``` - -### Prometheus Queries - -In those cases where operational metrics should be part of Usage Ping, a database or Redis query is unlikely -to provide useful data. Instead, Prometheus might be more appropriate, since most GitLab architectural -components publish metrics to it that can be queried back, aggregated, and included as usage data. - -NOTE: -Prometheus as a data source for Usage Ping is currently only available for single-node Omnibus installations -that are running the [bundled Prometheus](../administration/monitoring/prometheus/index.md) instance. - -To query Prometheus for metrics, a helper method is available to `yield` a fully configured -`PrometheusClient`, given it is available as per the note above: - -```ruby -with_prometheus_client do |client| - response = client.query('<your query>') - ... -end -``` - -Please refer to [the `PrometheusClient` definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb) -for how to use its API to query for data. - -## Developing and testing Usage Ping - -### 1. Naming and placing the metrics - -Add the metric in one of the top level keys - -- `license`: for license related metrics. -- `settings`: for settings related metrics. -- `counts_weekly`: for counters that have data for the most recent 7 days. -- `counts_monthly`: for counters that have data for the most recent 28 days. -- `counts`: for counters that have data for all time. - -### 2. Use your Rails console to manually test counters - -```ruby -# count -Gitlab::UsageData.count(User.active) -Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) - -# count distinct -Gitlab::UsageData.distinct_count(::Project, :creator_id) -Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) -``` - -### 3. Generate the SQL query - -Your Rails console returns the generated SQL queries. - -Example: - -```ruby -pry(main)> Gitlab::UsageData.count(User.active) - (2.6ms) SELECT "features"."key" FROM "features" - (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) - (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) - (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000 -``` - -### 4. Optimize queries with #database-lab - -Paste the SQL query into `#database-lab` to see how the query performs at scale. - -- `#database-lab` is a Slack channel which uses a production-sized environment to test your queries. -- GitLab.com’s production database has a 15 second timeout. -- Any single query must stay below [1 second execution time](query_performance.md#timing-guidelines-for-queries) with cold caches. -- Add a specialized index on columns involved to reduce the execution time. - -To have an understanding of the query's execution we add in the MR description the following information: - -- For counters that have a `time_period` test we add information for both cases: - - `time_period = {}` for all time periods - - `time_period = { created_at: 28.days.ago..Time.current }` for last 28 days period -- Execution plan and query time before and after optimization -- Query generated for the index and time -- Migration output for up and down execution - -We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/). For more details, see the [database review guide](database_review.md#preparation-when-adding-or-modifying-queries). - -#### Optimization recommendations and examples - -- Use specialized indexes [example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871), [example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445). -- Use defined `start` and `finish`, and simple queries, because these values can be memoized and reused, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155). -- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316). -- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000). - -### 5. Add the metric definition - -When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary). - -### 6. Add new metric to Versions Application - -Check if new metrics need to be added to the Versions Application. See `usage_data` [schema](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147) and usage data [parameters accepted](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb). Any metrics added under the `counts` key are saved in the `stats` column. - -### 7. Add the feature label - -Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature. - -### 8. Add a changelog file - -Ensure you comply with the [Changelog entries guide](changelog.md). - -### 9. Ask for a Product Intelligence Review - -On GitLab.com, we have DangerBot setup to monitor Product Intelligence related files and DangerBot recommends a Product Intelligence review. Mention `@gitlab-org/growth/product_intelligence/engineers` in your MR for a review. - -### 10. Verify your metric - -On GitLab.com, the Product Intelligence team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "SaaS" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric. - -### Optional: Test Prometheus based Usage Ping - -If the data submitted includes metrics [queried from Prometheus](#prometheus-queries) that you would like to inspect and verify, -then you need to ensure that a Prometheus server is running locally, and that furthermore the respective GitLab components -are exporting metrics to it. If you do not need to test data coming from Prometheus, no further action -is necessary, since Usage Ping should degrade gracefully in the absence of a running Prometheus server. - -There are currently three kinds of components that may export data to Prometheus, and which are included in Usage Ping: - -- [`node_exporter`](https://github.com/prometheus/node_exporter) - Exports node metrics from the host machine -- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter) - Exports process metrics from various GitLab components -- various GitLab services such as Sidekiq and the Rails server that export their own metrics - -#### Test with an Omnibus container - -This is the recommended approach to test Prometheus based Usage Ping. - -The easiest way to verify your changes is to build a new Omnibus image from your code branch by using CI, then download the image -and run a local container instance: - -1. From your merge request, click on the `qa` stage, then trigger the `package-and-qa` job. This job triggers an Omnibus -build in a [downstream pipeline of the `omnibus-gitlab-mirror` project](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines). -1. In the downstream pipeline, wait for the `gitlab-docker` job to finish. -1. Open the job logs and locate the full container name including the version. It takes the following form: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`. -1. On your local machine, make sure you are signed in to the GitLab Docker registry. You can find the instructions for this in -[Authenticate to the GitLab Container Registry](../user/packages/container_registry/index.md#authenticate-with-the-container-registry). -1. Once signed in, download the new image by using `docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` -1. For more information about working with and running Omnibus GitLab containers in Docker, please refer to [GitLab Docker images](https://docs.gitlab.com/omnibus/docker/README.html) in the Omnibus documentation. - -#### Test with GitLab development toolkits - -This is the less recommended approach, since it comes with a number of difficulties when emulating a real GitLab deployment. - -The [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) is not currently set up to run a Prometheus server or `node_exporter` alongside other GitLab components. If you would -like to do so, [Monitoring the GDK with Prometheus](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) is a good start. - -The [GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit) has limited support for testing Prometheus based Usage Ping. -By default, it already comes with a fully configured Prometheus service that is set up to scrape a number of components, -but with the following limitations: - -- It does not currently run a `gitlab-exporter` instance, so several `process_*` metrics from services such as Gitaly may be missing. -- While it runs a `node_exporter`, `docker-compose` services emulate hosts, meaning that it would normally report itself to not be associated -with any of the other services that are running. That is not how node metrics are reported in a production setup, where `node_exporter` -always runs as a process alongside other GitLab components on any given node. From Usage Ping's perspective none of the node data would therefore -appear to be associated to any of the services running, since they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Usage Ping. - -## Aggregated metrics - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6. - -WARNING: -This feature is intended solely for internal GitLab use. - -To add data for aggregated metrics into Usage Ping payload you should add corresponding definition in [`aggregated_metrics`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/). Each aggregate definition includes following parts: - -- name: unique name under which aggregate metric is added to Usage Ping payload -- operator: operator that defines how aggregated metric data is counted. Available operators are: - - `OR`: removes duplicates and counts all entries that triggered any of listed events - - `AND`: removes duplicates and counts all elements that were observed triggering all of following events -- events: list of events names (from [`known_events/`](#known-events-are-added-automatically-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes. -- feature_flag: name of [development feature flag](feature_flags/development.md#development-type) that is checked before -metrics aggregation is performed. Corresponding feature flag should have `default_enabled` attribute set to `false`. -`feature_flag` attribute is **OPTIONAL** and can be omitted, when `feature_flag` is missing no feature flag is checked. - -Example aggregated metric entries: - -```yaml -- name: product_analytics_test_metrics_union - operator: OR - events: ['i_search_total', 'i_search_advanced', 'i_search_paid'] -- name: product_analytics_test_metrics_intersection_with_feautre_flag - operator: AND - events: ['i_search_total', 'i_search_advanced', 'i_search_paid'] - feature_flag: example_aggregated_metric -``` - -Aggregated metrics are added under `aggregated_metrics` key in both `counts_weekly` and `counts_monthly` top level keys in Usage Ping payload. - -```ruby -{ - :counts_monthly => { - :deployments => 1003, - :successful_deployments => 78, - :failed_deployments => 275, - :packages => 155, - :personal_snippets => 2106, - :project_snippets => 407, - :promoted_issues => 719, - :aggregated_metrics => { - :product_analytics_test_metrics_union => 7, - :product_analytics_test_metrics_intersection_with_feautre_flag => 2 - }, - :snippets => 2513 - } -} -``` - -## Example Usage Ping payload - -The following is example content of the Usage Ping payload. - -```json -{ - "uuid": "0000000-0000-0000-0000-000000000000", - "hostname": "example.com", - "version": "12.10.0-pre", - "installation_type": "omnibus-gitlab", - "active_user_count": 999, - "recorded_at": "2020-04-17T07:43:54.162+00:00", - "edition": "EEU", - "license_md5": "00000000000000000000000000000000", - "license_id": null, - "historical_max_users": 999, - "licensee": { - "Name": "ABC, Inc.", - "Email": "email@example.com", - "Company": "ABC, Inc." - }, - "license_user_count": 999, - "license_starts_at": "2020-01-01", - "license_expires_at": "2021-01-01", - "license_plan": "ultimate", - "license_add_ons": { - }, - "license_trial": false, - "counts": { - "assignee_lists": 999, - "boards": 999, - "ci_builds": 999, - ... - }, - "container_registry_enabled": true, - "dependency_proxy_enabled": false, - "gitlab_shared_runners_enabled": true, - "gravatar_enabled": true, - "influxdb_metrics_enabled": true, - "ldap_enabled": false, - "mattermost_enabled": false, - "omniauth_enabled": true, - "prometheus_enabled": false, - "prometheus_metrics_enabled": false, - "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com", - "signup_enabled": true, - "web_ide_clientside_preview_enabled": true, - "ingress_modsecurity_enabled": true, - "projects_with_expiration_policy_disabled": 999, - "projects_with_expiration_policy_enabled": 999, - ... - "elasticsearch_enabled": true, - "license_trial_ends_on": null, - "geo_enabled": false, - "git": { - "version": { - "major": 2, - "minor": 26, - "patch": 1 - } - }, - "gitaly": { - "version": "12.10.0-rc1-93-g40980d40", - "servers": 56, - "clusters": 14, - "filesystems": [ - "EXT_2_3_4" - ] - }, - "gitlab_pages": { - "enabled": true, - "version": "1.17.0" - }, - "container_registry_server": { - "vendor": "gitlab", - "version": "2.9.1-gitlab" - }, - "database": { - "adapter": "postgresql", - "version": "9.6.15", - "pg_system_id": 6842684531675334351 - }, - "analytics_unique_visits": { - "g_analytics_contribution": 999, - ... - }, - "usage_activity_by_stage": { - "configure": { - "project_clusters_enabled": 999, - ... - }, - "create": { - "merge_requests": 999, - ... - }, - "manage": { - "events": 999, - ... - }, - "monitor": { - "clusters": 999, - ... - }, - "package": { - "projects_with_packages": 999 - }, - "plan": { - "issues": 999, - ... - }, - "release": { - "deployments": 999, - ... - }, - "secure": { - "user_container_scanning_jobs": 999, - ... - }, - "verify": { - "ci_builds": 999, - ... - } - }, - "usage_activity_by_stage_monthly": { - "configure": { - "project_clusters_enabled": 999, - ... - }, - "create": { - "merge_requests": 999, - ... - }, - "manage": { - "events": 999, - ... - }, - "monitor": { - "clusters": 999, - ... - }, - "package": { - "projects_with_packages": 999 - }, - "plan": { - "issues": 999, - ... - }, - "release": { - "deployments": 999, - ... - }, - "secure": { - "user_container_scanning_jobs": 999, - ... - }, - "verify": { - "ci_builds": 999, - ... - } - }, - "topology": { - "duration_s": 0.013836685999194742, - "application_requests_per_hour": 4224, - "query_apdex_weekly_average": 0.996, - "failures": [], - "nodes": [ - { - "node_memory_total_bytes": 33269903360, - "node_memory_utilization": 0.35, - "node_cpus": 16, - "node_cpu_utilization": 0.2, - "node_uname_info": { - "machine": "x86_64", - "sysname": "Linux", - "release": "4.19.76-linuxkit" - }, - "node_services": [ - { - "name": "web", - "process_count": 16, - "process_memory_pss": 233349888, - "process_memory_rss": 788220927, - "process_memory_uss": 195295487, - "server": "puma" - }, - { - "name": "sidekiq", - "process_count": 1, - "process_memory_pss": 734080000, - "process_memory_rss": 750051328, - "process_memory_uss": 731533312 - }, - ... - ], - ... - }, - ... - ] - } -} -``` - -## Notable changes - -In GitLab 13.5, `pg_system_id` was added to send the [PostgreSQL system identifier](https://www.2ndquadrant.com/en/blog/support-for-postgresqls-system-identifier-in-barman/). - -## Exporting Usage Ping SQL queries and definitions - -Two Rake tasks exist to export Usage Ping definitions. - -- The Rake tasks export the raw SQL queries for `count`, `distinct_count`, `sum`. -- The Rake tasks export the Redis counter class or the line of the Redis block for `redis_usage_data`. -- The Rake tasks calculate the `alt_usage_data` metrics. - -In the home directory of your local GitLab installation run the following Rake tasks for the YAML and JSON versions respectively: - -```shell -# for YAML export -bin/rake gitlab:usage_data:dump_sql_in_yaml - -# for JSON export -bin/rake gitlab:usage_data:dump_sql_in_json - -# You may pipe the output into a file -bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml -``` - -## Generating and troubleshooting usage ping - -To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping). +This document was moved to [another location](usage_ping/index.md). +<!-- This redirect file can be deleted after <2021-05-23>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
\ No newline at end of file diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md index ca3e0f1aae6..c0e9aa82247 100644 --- a/doc/development/usage_ping/dictionary.md +++ b/doc/development/usage_ping/dictionary.md @@ -24,864 +24,17590 @@ bundle exec rake gitlab:usage_data:generate_metrics_dictionary The Metrics Dictionary is based on the following metrics definition YAML files: -- [`config/metrics`]('https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/metrics') +- [`config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/metrics) - [`ee/config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/config/metrics) + Each table includes a `milestone`, which corresponds to the GitLab version when the metric was released. -## `active_user_count` +## Metrics Definitions + +### `active_user_count` This is named the instance_user_count in the Versions application. -| field | value | -| --- | --- | -| `key_path` | **`active_user_count`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | Database | -| `distribution` | ce, ee | -| `tier` | free, premium, ultimate | -| `skip_validation` | true | - -## `container_registry_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124829_active_user_count.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `analytics_unique_visits.analytics_unique_visits_for_any_target` + +Visits to any of the pages listed above per week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174908_analytics_unique_visits_for_any_target.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.analytics_unique_visits_for_any_target_monthly` + +Visits to any of the pages listed above per month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.g_analytics_contribution` + +Visits to /groups/:group/-/contribution_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174836_g_analytics_contribution.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.g_analytics_insights` + +Visits to /groups/:group/-/insights + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174838_g_analytics_insights.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.g_analytics_issues` + +Visits to /groups/:group/-/issues_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174840_g_analytics_issues.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.g_analytics_merge_request` + +Visits to /groups/:group/-/analytics/merge_request_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174902_g_analytics_merge_request.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.g_analytics_productivity` + +Visits to /groups/:group/-/analytics/productivity_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174842_g_analytics_productivity.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.g_analytics_valuestream` + +Visits to /groups/:group/-/analytics/value_stream_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174844_g_analytics_valuestream.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.i_analytics_cohorts` + +Visits to /-/instance_statistics/cohorts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174858_i_analytics_cohorts.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.i_analytics_dev_ops_score` + +Visits to /-/instance_statistics/dev_ops_score + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174900_i_analytics_dev_ops_score.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.i_analytics_instance_statistics` + +Visit to /admin/instance_statistics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174906_i_analytics_instance_statistics.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.p_analytics_code_reviews` + +Visits to /:group/:project/-/analytics/code_reviews + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174848_p_analytics_code_reviews.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.p_analytics_insights` + +Visits to /:group/:project/insights + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174852_p_analytics_insights.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.p_analytics_issues` + +Visits to /:group/:project/-/analytics/issues_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174854_p_analytics_issues.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.p_analytics_merge_request` + +Visits to /:group/:project/-/analytics/merge_request_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174904_p_analytics_merge_request.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.p_analytics_pipelines` + +Visits to /:group/:project/pipelines/charts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174846_p_analytics_pipelines.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.p_analytics_repo` + +Visits to /:group/:project/-/graphs/master/charts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174856_p_analytics_repo.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `analytics_unique_visits.p_analytics_valuestream` + +Visits to /:group/:project/-/value_stream_analytics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174850_p_analytics_valuestream.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `compliance_unique_visits.a_compliance_audit_events_api` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183912_a_compliance_audit_events_api.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `compliance_unique_visits.compliance_unique_visits_for_any_target` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183914_compliance_unique_visits_for_any_target.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `compliance_unique_visits.compliance_unique_visits_for_any_target_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183916_compliance_unique_visits_for_any_target_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `compliance_unique_visits.g_compliance_audit_events` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183906_g_compliance_audit_events.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `compliance_unique_visits.g_compliance_dashboard` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183904_g_compliance_dashboard.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `compliance_unique_visits.i_compliance_audit_events` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183908_i_compliance_audit_events.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `compliance_unique_visits.i_compliance_credential_inventory` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183910_i_compliance_credential_inventory.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `container_registry_enabled` Whether container registry is enabled -| field | value | -| --- | --- | -| `key_path` | **`container_registry_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `counts.deployments` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124858_container_registry_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `container_registry_server.vendor` + +Identifies if a user is using an external container registry and what type + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181051_vendor.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `container_registry_server.version` + +Identifies the version of the external registry being used + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216181053_version.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.alert_bot_incident_issues` + +Count of issues created by the alert bot automatically + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180449_alert_bot_incident_issues.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.all_searches` + +Total Searches for All Basic Search and Advanced Search in self-managed and SaaS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180413_all_searches.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.api_fuzzing_dnd_jobs` + +Count of API Fuzzing `docker-in-docker` jobs run by job name + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180346_api_fuzzing_dnd_jobs.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `free` + +### `counts.api_fuzzing_jobs` + +Count of API Fuzzing jobs run by job name + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180344_api_fuzzing_jobs.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `free` + +### `counts.assignee_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181100_assignee_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: + +### `counts.auto_devops_disabled` + +Projects with Auto DevOps template disabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175231_auto_devops_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free` + +### `counts.auto_devops_enabled` + +Projects with Auto DevOps template enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175229_auto_devops_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free` + +### `counts.boards` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181252_boards.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_builds` + +Unique builds in project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175510_ci_builds.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_external_pipelines` + +Total pipelines in external repositories + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175514_ci_external_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_internal_pipelines` + +Total pipelines in GitLab repositories + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175512_ci_internal_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_pipeline_config_auto_devops` + +Total pipelines from an Auto DevOps template + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175516_ci_pipeline_config_auto_devops.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_pipeline_config_repository` + +Total Pipelines from templates in repository + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175518_ci_pipeline_config_repository.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_pipeline_schedules` + +Pipeline schedules in GitLab + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175523_ci_pipeline_schedules.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_runners` + +Total configured Runners in project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175520_ci_runners.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.ci_triggers` + +Total configured Triggers in project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175521_ci_triggers.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `counts.clusters` + +Total GitLab Managed clusters both enabled and disabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175232_clusters.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_cert_managers` + +Total GitLab Managed clusters with GitLab Managed App:Cert Manager installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175259_clusters_applications_cert_managers.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_cilium` + +Total GitLab Managed clusters with GitLab Managed App:Cilium installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175312_clusters_applications_cilium.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_crossplane` + +Total GitLab Managed clusters with GitLab Managed App:Crossplane installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175301_clusters_applications_crossplane.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_elastic_stack` + +Total GitLab Managed clusters with GitLab Managed App:Elastic Stack installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175309_clusters_applications_elastic_stack.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_helm` + +Total GitLab Managed clusters with GitLab Managed App:Helm enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175255_clusters_applications_helm.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_ingress` + +Total GitLab Managed clusters with GitLab Managed App:Ingress installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175257_clusters_applications_ingress.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_jupyter` + +Total GitLab Managed clusters with GitLab Managed App:Jupyter installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175310_clusters_applications_jupyter.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_knative` + +Total GitLab Managed clusters with GitLab Managed App:Knative installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175307_clusters_applications_knative.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_prometheus` + +Total GitLab Managed clusters with GitLab Managed App:Prometheus installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175303_clusters_applications_prometheus.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_applications_runner` + +Total GitLab Managed clusters with GitLab Managed App:Runner installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175305_clusters_applications_runner.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_disabled` + +Total GitLab Managed disabled clusters + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175242_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_enabled` + +Total GitLab Managed clusters currently enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175234_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_management_project` + +Total GitLab Managed clusters with defined cluster management project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175314_clusters_management_project.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_platforms_eks` + +Total GitLab Managed clusters provisioned with GitLab on AWS EKS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175250_clusters_platforms_eks.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_platforms_gke` + +Total GitLab Managed clusters provisioned with GitLab on GCE GKE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175251_clusters_platforms_gke.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.clusters_platforms_user` + +Total GitLab Managed clusters that are user provisioned + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175253_clusters_platforms_user.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.commit_comment` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182004_commit_comment.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `counts.confidential_epics` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181205_confidential_epics.yml) + +Group: `group::portfolio management` + +Status: `data_available` + +Tiers: `free` + +### `counts.container_scanning_jobs` + +Count of Container Scanning jobs run + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175458_container_scanning_jobs.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.coverage_fuzzing_jobs` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183146_coverage_fuzzing_jobs.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.cycle_analytics_views` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174832_cycle_analytics_views.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `counts.dast_jobs` + +Count of DAST jobs run + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175612_dast_jobs.yml) + +Group: `group::dynamic analysis` + +Status: `data_available` + +Tiers: `free` + +### `counts.dast_on_demand_pipelines` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183149_dast_on_demand_pipelines.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.dependency_list_usages_total` + +Count to Dependency List page views + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175211_dependency_list_usages_total.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.dependency_scanning_jobs` + +Count of Dependency Scanning jobs run + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175213_dependency_scanning_jobs.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.deploy_keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181908_deploy_keys.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts.deployments` Total deployments count -| field | value | -| --- | --- | -| `key_path` | **`counts.deployments`** | -| `product_section` | ops | -| `product_stage` | release | -| `product_group` | `group::ops release` | -| `value_type` | number | -| `status` | data_available | -| `milestone` | 8.12 | -| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/735) | -| `time_frame` | all | -| `data_source` | Database | -| `distribution` | ee, ce | -| `tier` | free, premium, ultimate | - -## `counts.geo_nodes` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210201124934_deployments.yml) + +Group: `group::ops release` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.design_management_designs_create` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180740_design_management_designs_create.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `counts.design_management_designs_delete` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180743_design_management_designs_delete.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `counts.design_management_designs_update` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180741_design_management_designs_update.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `counts.environments` + +Total available and stopped environments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181914_environments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts.epic_issues` + +Count of issues that are assigned to an epic + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181208_epic_issues.yml) + +Group: `group::portfolio management` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.epics` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181206_epics.yml) + +Group: `group::portfolio management` + +Status: `data_available` + +Tiers: `free` + +### `counts.epics_deepest_relationship_level` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181212_epics_deepest_relationship_level.yml) + +Group: `group::portfolio management` + +Status: `data_available` + +Tiers: + +### `counts.failed_deployments` + +Total failed deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181912_failed_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts.feature_flags` + +Number of feature flag toggles + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181249_feature_flags.yml) + +Group: `group::progressive delivery` + +Status: `data_available` + +Tiers: `free` + +### `counts.geo_event_log_max_id` + +Number of replication events on a Geo primary + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180405_geo_event_log_max_id.yml) + +Group: `group::geo` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.geo_node_usage.git_fetch_event_count_weekly` + +Number of Git fetch events from Prometheus on the Geo secondary + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210309194425_git_fetch_event_count_weekly.yml) + +Group: `group::geo` + +Status: `implemented` + +Tiers: `premium`, `ultimate` + +### `counts.geo_nodes` Total number of sites in a Geo deployment -| field | value | -| --- | --- | -| `key_path` | **`counts.geo_nodes`** | -| `product_section` | enablement | -| `product_stage` | enablement | -| `product_group` | `group::geo` | -| `product_category` | disaster_recovery | -| `value_type` | integer | -| `status` | data_available | -| `milestone` | 11.2 | -| `time_frame` | all | -| `data_source` | Database | -| `distribution` | ee | -| `tier` | premium, ultimate | - -## `counts.license_management_jobs` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210201124936_geo_nodes.yml) + +Group: `group::geo` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.grafana_integrated_projects` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180927_grafana_integrated_projects.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `counts.group_clusters_disabled` + +Total GitLab Managed disabled clusters previously attached to groups + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175246_group_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.group_clusters_enabled` + +Total GitLab Managed clusters attached to groups + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175238_group_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups` + +Total count of groups as of usage ping snapshot + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180750_groups.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_asana_active` + +Count of groups with active integrations for Asana + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175625_groups_asana_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_assembla_active` + +Count of groups with active integrations for Assembla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175636_groups_assembla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_bamboo_active` + +Count of groups with active integrations for Bamboo CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175647_groups_bamboo_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_bugzilla_active` + +Count of groups with active integrations for Bugzilla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175659_groups_bugzilla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_buildkite_active` + +Count of groups with active integrations for Buildkite + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175710_groups_buildkite_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_campfire_active` + +Count of groups with active integrations for Campfire + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175721_groups_campfire_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_confluence_active` + +Count of groups with active integrations for Confluence + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175733_groups_confluence_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_custom_issue_tracker_active` + +Count of groups with active integrations for a Custom Issue Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175744_groups_custom_issue_tracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_datadog_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182549_groups_datadog_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_discord_active` + +Count of groups with active integrations for Discord + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175755_groups_discord_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_drone_ci_active` + +Count of groups with active integrations for Drone CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175806_groups_drone_ci_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_emails_on_push_active` + +Count of groups with active integrations for Emails on Push + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175817_groups_emails_on_push_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_ewm_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182616_groups_ewm_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_external_wiki_active` + +Count of groups with active integrations for External Wiki + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175828_groups_external_wiki_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_flowdock_active` + +Count of groups with active integrations for Flowdock + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175839_groups_flowdock_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_github_active` + +Count of groups with active integrations for GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175850_groups_github_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_hangouts_chat_active` + +Count of groups with active integrations for Hangouts Chat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175901_groups_hangouts_chat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_hipchat_active` + +Count of groups with active integrations for HipChat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175912_groups_hipchat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_asana_active` + +Count of active groups inheriting integrations for Asana + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175632_groups_inheriting_asana_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_assembla_active` + +Count of active groups inheriting integrations for Assembla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175644_groups_inheriting_assembla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_bamboo_active` + +Count of active groups inheriting integrations for Bamboo CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175655_groups_inheriting_bamboo_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_bugzilla_active` + +Count of active groups inheriting integrations for Bugzilla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175706_groups_inheriting_bugzilla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_buildkite_active` + +Count of active groups inheriting integrations for Buildkite + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175717_groups_inheriting_buildkite_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_campfire_active` + +Count of active groups inheriting integrations for Campfire + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175729_groups_inheriting_campfire_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_confluence_active` + +Count of active groups inheriting integrations for Confluence + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175740_groups_inheriting_confluence_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_custom_issue_tracker_active` + +Count of active groups inheriting integrations for a Custom Issue Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175751_groups_inheriting_custom_issue_tracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_datadog_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182557_groups_inheriting_datadog_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_inheriting_discord_active` + +Count of active groups inheriting integrations for Discord + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175802_groups_inheriting_discord_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_drone_ci_active` + +Count of active groups inheriting integrations for Drone CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175813_groups_inheriting_drone_ci_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_emails_on_push_active` + +Count of active groups inheriting integrations for Emails on Push + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175824_groups_inheriting_emails_on_push_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_ewm_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182623_groups_inheriting_ewm_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_inheriting_external_wiki_active` + +Count of active groups inheriting integrations for External Wiki + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175835_groups_inheriting_external_wiki_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_flowdock_active` + +Count of active groups inheriting integrations for Flowdock + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175846_groups_inheriting_flowdock_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_github_active` + +Count of active groups inheriting integrations for GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175857_groups_inheriting_github_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_hangouts_chat_active` + +Count of active groups inheriting integrations for Hangouts Chat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175908_groups_inheriting_hangouts_chat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_hipchat_active` + +Count of active groups inheriting integrations for HipChat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175919_groups_inheriting_hipchat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_irker_active` + +Count of active groups inheriting integrations for Irker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175930_groups_inheriting_irker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_jenkins_active` + +Count of active groups inheriting integrations for Jenkins + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175941_groups_inheriting_jenkins_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_jira_active` + +Count of active groups inheriting integrations for Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175952_groups_inheriting_jira_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_mattermost_active` + +Count of active groups inheriting integrations for Mattermost + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180003_groups_inheriting_mattermost_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_mattermost_slash_commands_active` + +Count of active groups inheriting integrations for Mattermost (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180014_groups_inheriting_mattermost_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_microsoft_teams_active` + +Count of active groups inheriting integrations for Microsoft Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180025_groups_inheriting_microsoft_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_mock_ci_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182732_groups_inheriting_mock_ci_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_inheriting_mock_monitoring_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182743_groups_inheriting_mock_monitoring_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_inheriting_packagist_active` + +Count of active groups inheriting integrations for Packagist + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180036_groups_inheriting_packagist_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_pipelines_email_active` + +Count of active groups inheriting integrations for Pipeline Emails + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180047_groups_inheriting_pipelines_email_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_pivotaltracker_active` + +Count of active groups inheriting integrations for Pivotal Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180058_groups_inheriting_pivotaltracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_prometheus_active` + +Count of active groups inheriting integrations for Prometheus + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180940_groups_inheriting_prometheus_active.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_pushover_active` + +Count of active groups inheriting integrations for Pushover + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180109_groups_inheriting_pushover_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_redmine_active` + +Count of active groups inheriting integrations for Redmine + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180120_groups_inheriting_redmine_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_slack_active` + +Count of active groups inheriting integrations for Slack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180131_groups_inheriting_slack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_slack_slash_commands_active` + +Count of active groups inheriting integrations for Slack (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180142_groups_inheriting_slack_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_teamcity_active` + +Count of active groups inheriting integrations for Teamcity CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180153_groups_inheriting_teamcity_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_unify_circuit_active` + +Count of active groups inheriting integrations for Unifiy Circuit + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180204_groups_inheriting_unify_circuit_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_webex_teams_active` + +Count of active groups inheriting integrations for Webex Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180215_groups_inheriting_webex_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_inheriting_youtrack_active` + +Count of active groups inheriting integrations for YouTrack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180226_groups_inheriting_youtrack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_irker_active` + +Count of groups with active integrations for Irker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175923_groups_irker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_jenkins_active` + +Count of groups with active integrations for Jenkins + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175934_groups_jenkins_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_jira_active` + +Count of groups with active integrations for Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175945_groups_jira_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_mattermost_active` + +Count of groups with active integrations for Mattermost + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175956_groups_mattermost_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_mattermost_slash_commands_active` + +Count of groups with active integrations for Mattermost (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180006_groups_mattermost_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_microsoft_teams_active` + +Count of groups with active integrations for Microsoft Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180018_groups_microsoft_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_mock_ci_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182724_groups_mock_ci_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_mock_monitoring_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182736_groups_mock_monitoring_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.groups_packagist_active` + +Count of groups with active integrations for Packagist + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180029_groups_packagist_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_pipelines_email_active` + +Count of groups with active integrations for Pipeline Emails + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180040_groups_pipelines_email_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_pivotaltracker_active` + +Count of groups with active integrations for Pivotal Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180051_groups_pivotaltracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_prometheus_active` + +Count of groups with active integrations for Prometheus + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180933_groups_prometheus_active.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_pushover_active` + +Count of groups with active integrations for Pushover + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180102_groups_pushover_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_redmine_active` + +Count of groups with active integrations for Redmine + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180113_groups_redmine_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_slack_active` + +Count of groups with active integrations for Slack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180124_groups_slack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_slack_slash_commands_active` + +Count of groups with active integrations for Slack (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180135_groups_slack_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_teamcity_active` + +Count of groups with active integrations for Teamcity CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180146_groups_teamcity_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_unify_circuit_active` + +Count of groups with active integrations for Unifiy Circuit + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180157_groups_unify_circuit_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_webex_teams_active` + +Count of groups with active integrations for Webex Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180208_groups_webex_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.groups_youtrack_active` + +Count of groups with active integrations for YouTrack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180219_groups_youtrack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.in_review_folder` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181916_in_review_folder.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts.incident_issues` + +Count of incidents (issues where issue_type=incident) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180447_incident_issues.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.incident_labeled_issues` + +Count of all issues with the label=incident + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180451_incident_labeled_issues.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ingress_modsecurity_blocking` + +Whether or not ModSecurity is set to blocking mode + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175452_ingress_modsecurity_blocking.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ingress_modsecurity_disabled` + +Whether or not ModSecurity is disabled within Ingress + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175454_ingress_modsecurity_disabled.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ingress_modsecurity_logging` + +Whether or not ModSecurity is set to logging mode + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175450_ingress_modsecurity_logging.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ingress_modsecurity_not_installed` + +Whether or not ModSecurity has not been installed into the cluster + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175456_ingress_modsecurity_not_installed.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ingress_modsecurity_packets_anomalous` + +Cumulative count of packets identified as anomalous by ModSecurity since Usage Ping was last reported + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175444_ingress_modsecurity_packets_anomalous.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ingress_modsecurity_packets_processed` + +Cumulative count of packets processed by ModSecurity since Usage Ping was last reported + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175442_ingress_modsecurity_packets_processed.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ingress_modsecurity_statistics_unavailable` + +Whether or not ModSecurity statistics are unavailable + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175441_ingress_modsecurity_statistics_unavailable.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.instance_clusters_disabled` + +Total GitLab Managed disabled clusters previously attached to the instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175248_instance_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instance_clusters_enabled` + +Total GitLab Managed clusters attached to the instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175240_instance_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_asana_active` + +Count of active instance-level integrations for Asana + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175628_instances_asana_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_assembla_active` + +Count of active instance-level integrations for Assembla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175640_instances_assembla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_bamboo_active` + +Count of active instance-level integrations for Bamboo CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175651_instances_bamboo_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_bugzilla_active` + +Count of active instance-level integrations for Bugzilla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175702_instances_bugzilla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_buildkite_active` + +Count of active instance-level integrations for Buildkite + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175714_instances_buildkite_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_campfire_active` + +Count of active instance-level integrations for Campfire + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175725_instances_campfire_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_confluence_active` + +Count of active instance-level integrations for Confluence + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175736_instances_confluence_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_custom_issue_tracker_active` + +Count of active instance-level integrations for a Custom Issue Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175747_instances_custom_issue_tracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_datadog_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182553_instances_datadog_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.instances_discord_active` + +Count of active instance-level integrations for Discord + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175758_instances_discord_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_drone_ci_active` + +Count of active instance-level integrations for Drone CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175809_instances_drone_ci_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_emails_on_push_active` + +Count of active instance-level integrations for Emails on Push + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175820_instances_emails_on_push_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_ewm_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182620_instances_ewm_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.instances_external_wiki_active` + +Count of active instance-level integrations for External Wiki + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175831_instances_external_wiki_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_flowdock_active` + +Count of active instance-level integrations for Flowdock + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175842_instances_flowdock_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_github_active` + +Count of active instance-level integrations for GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175853_instances_github_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_hangouts_chat_active` + +Count of active instance-level integrations for Hangouts Chat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175904_instances_hangouts_chat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_hipchat_active` + +Count of active instance-level integrations for HipChat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175915_instances_hipchat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_irker_active` + +Count of active instance-level integrations for Irker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175926_instances_irker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_jenkins_active` + +Count of active instance-level integrations for Jenkins + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175937_instances_jenkins_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_jira_active` + +Count of active instance-level integrations for Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175948_instances_jira_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_mattermost_active` + +Count of active instance-level integrations for Mattermost + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175959_instances_mattermost_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_mattermost_slash_commands_active` + +Count of active instance-level integrations for Mattermost (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180010_instances_mattermost_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_microsoft_teams_active` + +Count of active instance-level integrations for Microsoft Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180021_instances_microsoft_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_mock_ci_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182728_instances_mock_ci_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.instances_mock_monitoring_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182739_instances_mock_monitoring_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.instances_packagist_active` + +Count of active instance-level integrations for Packagist + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180032_instances_packagist_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_pipelines_email_active` + +Count of active instance-level integrations for Pipeline Emails + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180043_instances_pipelines_email_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_pivotaltracker_active` + +Count of active instance-level integrations for Pivotal Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180054_instances_pivotaltracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_prometheus_active` + +Count of active instance-level integrations for Prometheus + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180936_instances_prometheus_active.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_pushover_active` + +Count of active instance-level integrations for Pushover + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180105_instances_pushover_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_redmine_active` + +Count of active instance-level integrations for Redmine + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180116_instances_redmine_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_slack_active` + +Count of active instance-level integrations for Slack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180127_instances_slack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_slack_slash_commands_active` + +Count of active instance-level integrations for Slack (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180138_instances_slack_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_teamcity_active` + +Count of active instance-level integrations for Teamcity CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180149_instances_teamcity_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_unify_circuit_active` + +Count of active instance-level integrations for Unifiy Circuit + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180201_instances_unify_circuit_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_webex_teams_active` + +Count of active instance-level integrations for Webex Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180212_instances_webex_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.instances_youtrack_active` + +Count of active instance-level integrations for YouTrack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180223_instances_youtrack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues` + +Count of Issues created + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181102_issues.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues_created_from_alerts` + +Count of issues created automatically on alerts from GitLab-Managed Prometheus + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180441_issues_created_from_alerts.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues_created_from_gitlab_error_tracking_ui` + +Count of issues manually created from the GitLab UI on Sentry errors + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180434_issues_created_from_gitlab_error_tracking_ui.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.issues_created_gitlab_alerts` + +Count of all issues created from GitLab alerts (bot and non-bot) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180443_issues_created_gitlab_alerts.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues_created_manually_from_alerts` + +Count of issues created manually by non-bot users from GitLab alerts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180445_issues_created_manually_from_alerts.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues_using_zoom_quick_actions` + +Count of issues where a user have added AND removed a zoom meeting using slash commands + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180438_issues_using_zoom_quick_actions.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues_with_associated_zoom_link` + +Count of issues where a user has linked a Zoom meeting + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180436_issues_with_associated_zoom_link.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues_with_embedded_grafana_charts_approx` + +Count of issues where a user has embedded a Grafana chart + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180440_issues_with_embedded_grafana_charts_approx.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.issues_with_health_status` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181210_issues_with_health_status.yml) + +Group: `group::portfolio management` + +Status: `data_available` + +Tiers: `free` + +### `counts.jira_imports_projects_count` + +Count of Projects that imported Issues from Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181259_jira_imports_projects_count.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.jira_imports_total_imported_count` + +Count of Issues imported from Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181258_jira_imports_total_imported_count.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.jira_imports_total_imported_issues_count` + +Count of Jira imports run + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181301_jira_imports_total_imported_issues_count.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180752_keys.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `counts.kubernetes_agent_gitops_sync` + +Count of GitOps Sync events + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175328_kubernetes_agent_gitops_sync.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.kubernetes_agents` + +Count of Kubernetes agents + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175316_kubernetes_agents.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.kubernetes_agents_with_token` + +Count of Kubernetes agents with at least one token + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175318_kubernetes_agents_with_token.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.label_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181104_label_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `counts.labels` + +Count of Labels + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181111_labels.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.ldap_group_links` + +Number of groups that are synced via LDAP group sync `https://docs.gitlab.com/ee/user/group/index.html#manage-group-memberships-via-ldap` + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216174822_ldap_group_links.yml) + +Group: `group::access` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.ldap_keys` + +Number of keys synced as part of LDAP `https://docs.gitlab.com/ee/administration/auth/ldap/#ldap-sync-configuration-settings` + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216174824_ldap_keys.yml) + +Group: `group::access` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.ldap_users` + +Number of users that are linked to LDAP + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174826_ldap_users.yml) + +Group: `group::access` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.lfs_objects` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181009_lfs_objects.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.license_management_jobs` Name on the GitLab license -| field | value | -| --- | --- | -| `key_path` | **`counts.license_management_jobs`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | number | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | Database | -| `distribution` | | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `counts_monthly.deployments` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124854_license_management_jobs.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.licenses_list_views` + +Count to License List page views + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210216175210_licenses_list_views.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.merge_request_comment` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175041_merge_request_comment.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `counts.merge_request_create` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175043_merge_request_create.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `counts.merge_requests` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175039_merge_requests.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `counts.merged_merge_requests_using_approval_rules` + +Count of merge requests merged using approval rules + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175206_merged_merge_requests_using_approval_rules.yml) + +Group: `group::compliance` + +Status: `data_available` + +Tiers: `free` + +### `counts.milestone_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181106_milestone_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `counts.milestones` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181108_milestones.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `counts.navbar_searches` + +Total Searches using the navbar for All Basic Search and Advanced Search in self-managed and SaaS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180414_navbar_searches.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.network_policy_drops` + +Cumulative count of packets dropped by Cilium (Container Network Security) since Usage Ping was last reported + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175448_network_policy_drops.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.network_policy_forwards` + +Cumulative count of packets forwarded by Cilium (Container Network Security) since Usage Ping was last reported + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175446_network_policy_forwards.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.notes` + +Count of Notes across all objects that use them + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181113_notes.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.operations_dashboard_default_dashboard` + +Active users with enabled operations dashboard + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180942_operations_dashboard_default_dashboard.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `counts.operations_dashboard_users_with_projects_added` + +Active users with projects on operations dashboard + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180944_operations_dashboard_users_with_projects_added.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_composer_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_composer_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_composer_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_conan_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_conan_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_conan_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_container_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182907_package_events_i_package_container_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_container_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182909_package_events_i_package_container_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_container_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182911_package_events_i_package_container_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_debian_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_debian_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_debian_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182917_package_events_i_package_debian_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_delete_package_by_deploy_token` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_delete_package_by_guest` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_delete_package_by_user` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_generic_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_generic_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_generic_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_golang_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_golang_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_golang_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_maven_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_maven_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_maven_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_npm_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_npm_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_npm_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_nuget_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_nuget_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_nuget_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_pull_package_by_deploy_token` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_pull_package_by_guest` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_pull_package_by_user` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_push_package_by_deploy_token` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_push_package_by_guest` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_push_package_by_user` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_pypi_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_pypi_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_pypi_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_rubygems_delete_package` + +Total count of RubyGems packages delete events + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210303153000_package_events_i_package_rubygems_delete_package.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.package_events_i_package_rubygems_pull_package` + +Total count of pull RubyGems packages events + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210303153002_package_events_i_package_rubygems_pull_package.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.package_events_i_package_rubygems_push_package` + +Total count of push RubyGems packages events + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.package_events_i_package_tag_delete_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183017_package_events_i_package_tag_delete_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_tag_pull_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183019_package_events_i_package_tag_pull_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.package_events_i_package_tag_push_package` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183021_package_events_i_package_tag_push_package.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.packages` + +Number of packages + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181012_packages.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.pages_domains` + +Total GitLab Pages domains + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181946_pages_domains.yml) + +Group: `group::release management` + +Status: `data_available` + +Tiers: `free` + +### `counts.personal_snippets` + +Count of Personal Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180239_personal_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.pod_logs_usages_total` + +Count the total number of log views + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175021_pod_logs_usages_total.yml) + +Group: `group::apm` + +Status: `data_available` + +Tiers: `free` + +### `counts.pool_repositories` + +Count of unique object pool repositories for fork deduplication + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180410_pool_repositories.yml) + +Group: `group::gitaly` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.productivity_analytics_views` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174834_productivity_analytics_views.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `counts.project_clusters_disabled` + +Total GitLab Managed disabled clusters previously attached to projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175244_project_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.project_clusters_enabled` + +Total GitLab Managed clusters attached to projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175236_project_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.project_snippets` + +Count of Project Snippetss + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180241_project_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects` + +Count of Projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181254_projects.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_asana_active` + +Count of projects with active integrations for Asana + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175623_projects_asana_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_assembla_active` + +Count of projects with active integrations for Assembla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175634_projects_assembla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_bamboo_active` + +Count of projects with active integrations for Bamboo CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175645_projects_bamboo_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_bugzilla_active` + +Count of projects with active integrations for Bugzilla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175657_projects_bugzilla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_buildkite_active` + +Count of projects with active integrations for Buildkite + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175708_projects_buildkite_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_campfire_active` + +Count of projects with active integrations for Campfire + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175719_projects_campfire_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_confluence_active` + +Count of projects with active integrations for Confluence + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175731_projects_confluence_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_creating_incidents` + +Counts of Projects that have created incidents + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180453_projects_creating_incidents.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_custom_issue_tracker_active` + +Count of projects with active integrations for a Custom Issue Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175742_projects_custom_issue_tracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_datadog_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182547_projects_datadog_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_discord_active` + +Count of projects with active integrations for Discord + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175753_projects_discord_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_drone_ci_active` + +Count of projects with active integrations for Drone CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175804_projects_drone_ci_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_emails_on_push_active` + +Count of projects with active integrations for Emails on Push + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175815_projects_emails_on_push_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_ewm_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182614_projects_ewm_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_external_wiki_active` + +Count of projects with active integrations for External Wiki + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175826_projects_external_wiki_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_flowdock_active` + +Count of projects with active integrations for Flowdock + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175837_projects_flowdock_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_github_active` + +Count of projects with active integrations for GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175848_projects_github_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_hangouts_chat_active` + +Count of projects with active integrations for Hangouts Chat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175859_projects_hangouts_chat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_hipchat_active` + +Count of projects with active integrations for HipChat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175910_projects_hipchat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_imported_from_github` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180628_projects_imported_from_github.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_inheriting_asana_active` + +Count of active projects inheriting integrations for Asana + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175630_projects_inheriting_asana_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_assembla_active` + +Count of active projects inheriting integrations for Assembla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175642_projects_inheriting_assembla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_bamboo_active` + +Count of active projects inheriting integrations for Bamboo CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175653_projects_inheriting_bamboo_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_bugzilla_active` + +Count of active projects inheriting integrations for Bugzilla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175704_projects_inheriting_bugzilla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_buildkite_active` + +Count of active projects inheriting integrations for Buildkite + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175716_projects_inheriting_buildkite_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_campfire_active` + +Count of active projects inheriting integrations for Campfire + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175727_projects_inheriting_campfire_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_confluence_active` + +Count of active projects inheriting integrations for Confluence + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175738_projects_inheriting_confluence_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_custom_issue_tracker_active` + +Count of active projects inheriting integrations for a Custom Issue Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175749_projects_inheriting_custom_issue_tracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_datadog_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182555_projects_inheriting_datadog_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_inheriting_discord_active` + +Count of active projects inheriting integrations for Discord + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175800_projects_inheriting_discord_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_drone_ci_active` + +Count of active projects inheriting integrations for Drone CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175811_projects_inheriting_drone_ci_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_emails_on_push_active` + +Count of active projects inheriting integrations for Emails on Push + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175822_projects_inheriting_emails_on_push_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_ewm_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182622_projects_inheriting_ewm_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_inheriting_external_wiki_active` + +Count of active projects inheriting integrations for External Wiki + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175833_projects_inheriting_external_wiki_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_flowdock_active` + +Count of active projects inheriting integrations for Flowdock + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175844_projects_inheriting_flowdock_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_github_active` + +Count of active projects inheriting integrations for GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175855_projects_inheriting_github_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_hangouts_chat_active` + +Count of active projects inheriting integrations for Hangouts Chat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175906_projects_inheriting_hangouts_chat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_hipchat_active` + +Count of active projects inheriting integrations for HipChat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175917_projects_inheriting_hipchat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_irker_active` + +Count of active projects inheriting integrations for Irker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175928_projects_inheriting_irker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_jenkins_active` + +Count of active projects inheriting integrations for Jenkins + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175939_projects_inheriting_jenkins_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_jira_active` + +Count of active projects inheriting integrations for Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175950_projects_inheriting_jira_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_mattermost_active` + +Count of active projects inheriting integrations for Mattermost + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180001_projects_inheriting_mattermost_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_mattermost_slash_commands_active` + +Count of active projects inheriting integrations for Mattermost (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180012_projects_inheriting_mattermost_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_microsoft_teams_active` + +Count of active projects inheriting integrations for Microsoft Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180023_projects_inheriting_microsoft_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_mock_ci_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182730_projects_inheriting_mock_ci_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_inheriting_mock_monitoring_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182741_projects_inheriting_mock_monitoring_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_inheriting_packagist_active` + +Count of active projects inheriting integrations for Packagist + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180034_projects_inheriting_packagist_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_pipelines_email_active` + +Count of active projects inheriting integrations for Pipeline Emails + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180045_projects_inheriting_pipelines_email_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_pivotaltracker_active` + +Count of active projects inheriting integrations for Pivotal Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180056_projects_inheriting_pivotaltracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_prometheus_active` + +Count of active projects inheriting integrations for Prometheus + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180938_projects_inheriting_prometheus_active.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_pushover_active` + +Count of active projects inheriting integrations for Pushover + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180107_projects_inheriting_pushover_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_redmine_active` + +Count of active projects inheriting integrations for Redmine + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180118_projects_inheriting_redmine_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_slack_active` + +Count of active projects inheriting integrations for Slack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180129_projects_inheriting_slack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_slack_slash_commands_active` + +Count of active projects inheriting integrations for Slack (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180140_projects_inheriting_slack_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_teamcity_active` + +Count of active projects inheriting integrations for Teamcity CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180151_projects_inheriting_teamcity_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_unify_circuit_active` + +Count of active projects inheriting integrations for Unifiy Circuit + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180203_projects_inheriting_unify_circuit_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_webex_teams_active` + +Count of active projects inheriting integrations for Webex Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180214_projects_inheriting_webex_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_inheriting_youtrack_active` + +Count of active projects inheriting integrations for YouTrack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180225_projects_inheriting_youtrack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_irker_active` + +Count of projects with active integrations for Irker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175921_projects_irker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_jenkins_active` + +Count of projects with active integrations for Jenkins + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175932_projects_jenkins_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_jira_active` + +Count of projects with active integrations for Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175943_projects_jira_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_jira_cloud_active` + +Count of active integrations with Jira Cloud (Saas) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180230_projects_jira_cloud_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_jira_dvcs_cloud_active` + +Count of active integrations with Jira Cloud (DVCS Connector) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180232_projects_jira_dvcs_cloud_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_jira_dvcs_server_active` + +Count of active integrations with Jira Software (DVCS connector) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180234_projects_jira_dvcs_server_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_jira_issuelist_active` + +Total Jira Issue feature enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180236_projects_jira_issuelist_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.projects_jira_server_active` + +Count of active integrations with Jira Software (server) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180228_projects_jira_server_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_mattermost_active` + +Count of projects with active integrations for Mattermost + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175954_projects_mattermost_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_mattermost_slash_commands_active` + +Count of projects with active integrations for Mattermost (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180005_projects_mattermost_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_microsoft_teams_active` + +Count of projects with active integrations for Microsoft Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180016_projects_microsoft_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_mirrored_with_pipelines_enabled` + +Projects with repository mirroring enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181920_projects_mirrored_with_pipelines_enabled.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_mock_ci_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182722_projects_mock_ci_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_mock_monitoring_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182734_projects_mock_monitoring_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_packagist_active` + +Count of projects with active integrations for Packagist + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180027_projects_packagist_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_pipelines_email_active` + +Count of projects with active integrations for Pipeline Emails + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180038_projects_pipelines_email_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_pivotaltracker_active` + +Count of projects with active integrations for Pivotal Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180049_projects_pivotaltracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_prometheus_active` + +Count of projects with active integrations for Prometheus + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180931_projects_prometheus_active.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_pushover_active` + +Count of projects with active integrations for Pushover + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180100_projects_pushover_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_redmine_active` + +Count of projects with active integrations for Redmine + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180111_projects_redmine_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_reporting_ci_cd_back_to_github` + +Projects with a GitHub service pipeline enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182212_projects_reporting_ci_cd_back_to_github.yml) + +Group: `group::continuous_integration` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `counts.projects_slack_active` + +Count of projects with active integrations for Slack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180122_projects_slack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_slack_slash_commands_active` + +Count of projects with active integrations for Slack (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180133_projects_slack_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_teamcity_active` + +Count of projects with active integrations for Teamcity CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180144_projects_teamcity_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_unify_circuit_active` + +Count of projects with active integrations for Unifiy Circuit + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180155_projects_unify_circuit_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_webex_teams_active` + +Count of projects with active integrations for Webex Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180206_projects_webex_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_with_alerts_created` + +Count of projects with alerts created in given time period + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180458_projects_with_alerts_created.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_alerts_service_enabled` + +Count of projects that have enabled the Alerts service + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180456_projects_with_alerts_service_enabled.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_with_enabled_alert_integrations` + +Count of projects with at least 1 enabled integration + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180500_projects_with_enabled_alert_integrations.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_error_tracking_enabled` + +Count of projects that have enabled Error tracking via Sentry + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180454_projects_with_error_tracking_enabled.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.projects_with_expiration_policy_disabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181016_projects_with_expiration_policy_enabled.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_14d` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181033_projects_with_expiration_policy_enabled_with_cadence_set_to_14d.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_1d` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181029_projects_with_expiration_policy_enabled_with_cadence_set_to_1d.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_1month` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181035_projects_with_expiration_policy_enabled_with_cadence_set_to_1month.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_3month` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181037_projects_with_expiration_policy_enabled_with_cadence_set_to_3month.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_cadence_set_to_7d` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181031_projects_with_expiration_policy_enabled_with_cadence_set_to_7d.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_1` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181018_projects_with_expiration_policy_enabled_with_keep_n_set_to_1.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: + +### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_10` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181022_projects_with_expiration_policy_enabled_with_keep_n_set_to_10.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: + +### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_100` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181027_projects_with_expiration_policy_enabled_with_keep_n_set_to_100.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: + +### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_25` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181024_projects_with_expiration_policy_enabled_with_keep_n_set_to_25.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: + +### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_5` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181020_projects_with_expiration_policy_enabled_with_keep_n_set_to_5.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: + +### `counts.projects_with_expiration_policy_enabled_with_keep_n_set_to_50` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181025_projects_with_expiration_policy_enabled_with_keep_n_set_to_50.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: + +### `counts.projects_with_expiration_policy_enabled_with_keep_n_unset` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181046_projects_with_expiration_policy_enabled_with_keep_n_unset.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: + +### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_14d` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181040_projects_with_expiration_policy_enabled_with_older_than_set_to_14d.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_30d` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181042_projects_with_expiration_policy_enabled_with_older_than_set_to_30d.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_7d` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181038_projects_with_expiration_policy_enabled_with_older_than_set_to_7d.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_older_than_set_to_90d` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181044_projects_with_expiration_policy_enabled_with_older_than_set_to_90d.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_expiration_policy_enabled_with_older_than_unset` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181048_projects_with_expiration_policy_enabled_with_older_than_unset.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_packages` + +Projects with package registry configured + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181011_projects_with_packages.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_prometheus_alerts` + +Projects with Prometheus alerting enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175019_projects_with_prometheus_alerts.yml) + +Group: `group::apm` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_repositories_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181959_projects_with_repositories_enabled.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_terraform_reports` + +Count of projects with Terraform MR reports + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175320_projects_with_terraform_reports.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_terraform_states` + +Count of projects with GitLab Managed Terraform State + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175322_projects_with_terraform_states.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_with_tracing_enabled` + +Projects with tracing enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180929_projects_with_tracing_enabled.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `counts.projects_youtrack_active` + +Count of projects with active integrations for YouTrack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180217_projects_youtrack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.protected_branches` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182001_protected_branches.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `counts.protected_branches_except_default` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182454_protected_branches_except_default.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.releases` + +Unique release tags + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181918_releases.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts.remote_mirrors` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182002_remote_mirrors.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `counts.requirement_test_reports_ci` + +Count of requirement test reports created from CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175032_requirement_test_reports_ci.yml) + +Group: `group::certify` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.requirement_test_reports_manual` + +Count of requirement test reports created manually + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175030_requirement_test_reports_manual.yml) + +Group: `group::certify` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.requirements_created` + +Count of requirements created + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175028_requirements_created.yml) + +Group: `group::certify` + +Status: `data_available` + +Tiers: `free` + +### `counts.requirements_with_test_report` + +Count of requirements having a test report + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175034_requirements_with_test_report.yml) + +Group: `group::certify` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.sast_jobs` + +Count of SAST CI jobs for the month. Job names ending in '-sast' + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182112_sast_jobs.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.secret_detection_jobs` + +Count of 'secret-detection' CI jobs fro the month. + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182114_secret_detection_jobs.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.service_desk_enabled_projects` + +Count of service desk enabled projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175024_service_desk_enabled_projects.yml) + +Group: `group::certify` + +Status: `data_available` + +Tiers: `free` + +### `counts.service_desk_issues` + +Count of service desk issues + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175026_service_desk_issues.yml) + +Group: `group::certify` + +Status: `data_available` + +Tiers: `free` + +### `counts.snippet_comment` + +Count of comments on Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180253_snippet_comment.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.snippet_create` + +Count of newly created Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180255_snippet_create.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.snippet_update` + +Count of updates to existing Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180257_snippet_update.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.snippets` + +Count of all Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180306_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.source_code_pushes` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182006_source_code_pushes.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `counts.static_site_editor_commits` + +Count of commits created via Static Site Editor + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180301_static_site_editor_commits.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `counts.static_site_editor_merge_requests` + +Count of merge requests created via Static Site Editor + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180303_static_site_editor_merge_requests.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `counts.static_site_editor_views` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180259_static_site_editor_views.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.status_page_incident_publishes` + +Cumulative count of usages of publish operation + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180502_status_page_incident_publishes.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.status_page_incident_unpublishes` + +Cumulative count of usages of unpublish operation + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180504_status_page_incident_unpublishes.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.status_page_issues` + +Issues published to a Status Page + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180507_status_page_issues.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.status_page_projects` + +Projects with status page enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180506_status_page_projects.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts.successful_deployments` + +Total successful deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181911_successful_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts.suggestions` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175037_suggestions.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `counts.template_repositories` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182008_template_repositories.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `counts.templates_asana_active` + +Count of active service templates for Asana + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175627_templates_asana_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_assembla_active` + +Count of active service templates for Assembla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175638_templates_assembla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_bamboo_active` + +Count of active service templates for Bamboo CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_bugzilla_active` + +Count of active service templates for Bugzilla + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_buildkite_active` + +Count of active service templates for Buildkite + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_campfire_active` + +Count of active service templates for Campfire + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175723_templates_campfire_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_confluence_active` + +Count of active service templates for Confluence + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175734_templates_confluence_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_custom_issue_tracker_active` + +Count of active service templates for a Custom Issue Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_datadog_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182551_templates_datadog_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.templates_discord_active` + +Count of active service templates for Discord + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175756_templates_discord_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_drone_ci_active` + +Count of active service templates for Drone CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_emails_on_push_active` + +Count of active service templates for Emails on Push + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_ewm_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182618_templates_ewm_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.templates_external_wiki_active` + +Count of active service templates for External Wiki + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_flowdock_active` + +Count of active service templates for Flowdock + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_github_active` + +Count of active service templates for GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175851_templates_github_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_hangouts_chat_active` + +Count of active service templates for Hangouts Chat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_hipchat_active` + +Count of active service templates for HipChat + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175913_templates_hipchat_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_irker_active` + +Count of active service templates for Irker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175924_templates_irker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_jenkins_active` + +Count of active service templates for Jenkins + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_jira_active` + +Count of active service templates for Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175946_templates_jira_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_mattermost_active` + +Count of active service templates for Mattermost + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_mattermost_slash_commands_active` + +Count of active service templates for Mattermost (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_microsoft_teams_active` + +Count of active service templates for Microsoft Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_mock_ci_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182726_templates_mock_ci_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.templates_mock_monitoring_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182738_templates_mock_monitoring_active.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts.templates_packagist_active` + +Count of active service templates for Packagist + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180030_templates_packagist_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_pipelines_email_active` + +Count of active service templates for Pipeline Emails + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_pivotaltracker_active` + +Count of active service templates for Pivotal Tracker + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_prometheus_active` + +Count of active service templates for Prometheus + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180934_templates_prometheus_active.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_pushover_active` + +Count of active service templates for Pushover + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180104_templates_pushover_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_redmine_active` + +Count of active service templates for Redmine + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180115_templates_redmine_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_slack_active` + +Count of active service templates for Slack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180126_templates_slack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_slack_slash_commands_active` + +Count of active service templates for Slack (slash commands) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_teamcity_active` + +Count of active service templates for Teamcity CI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_unify_circuit_active` + +Count of active service templates for Unifiy Circuit + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_webex_teams_active` + +Count of active service templates for Webex Teams + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.templates_youtrack_active` + +Count of active service templates for YouTrack + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.terraform_reports` + +Count of Terraform MR reports generated + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175324_terraform_reports.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free` + +### `counts.terraform_states` + +Count of GitLab Managed Terraform States used + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175326_terraform_states.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free` + +### `counts.todos` + +Count of ToDos + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181256_todos.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.uploads` + +Count of Uploads via Notes and Descriptions + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181109_uploads.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.user_preferences_group_overview_details` + +Count of users who set personal preference to see Details on Group overview page + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182203_user_preferences_group_overview_details.yml) + +Group: `group::threat insights` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.user_preferences_group_overview_security_dashboard` + +Count of users who set personal preference to see Security Dashboard on Group overview page + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182205_user_preferences_group_overview_security_dashboard.yml) + +Group: `group::threat insights` + +Status: `data_available` + +Tiers: `ultimate` + +### `counts.user_preferences_user_gitpod_enabled` + +Count all users with their GitPod setting enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180304_user_preferences_user_gitpod_enabled.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.web_hooks` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175621_web_hooks.yml) + +Group: `group::ecosystem` + +Status: `data_available` + +Tiers: `free` + +### `counts.web_ide_commits` + +Count of Commits made from Web IDE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180242_web_ide_commits.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.web_ide_merge_requests` + +Count of Merge Requests created from Web IDE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180246_web_ide_merge_requests.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.web_ide_pipelines` + +Count of Pipeline tab views in Web IDE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180252_web_ide_pipelines.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.web_ide_previews` + +Count of Live Preview tab views in Web IDE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180248_web_ide_previews.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.web_ide_terminals` + +Count of Web Terminal Tab views in Web IDE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180250_web_ide_terminals.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.web_ide_views` + +Count of Views of the Web IDE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180244_web_ide_views.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts.wiki_pages_create` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180734_wiki_pages_create.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `counts.wiki_pages_delete` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180738_wiki_pages_delete.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `counts.wiki_pages_update` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180736_wiki_pages_update.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `counts.wiki_pages_view` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183023_wiki_pages_view.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.aggregated_metrics.compliance_features_track_unique_visits_union` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183201_compliance_features_track_unique_visits_union.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.aggregated_metrics.i_testing_paid_monthly_active_user_total` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183209_i_testing_paid_monthly_active_user_total.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.aggregated_metrics.incident_management_alerts_total_unique_counts` + +Count of unique users per month to take an action on an alert + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180509_incident_management_alerts_total_unique_counts.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.aggregated_metrics.incident_management_incidents_total_unique_counts` + +Count of unique users per month to take an action on an incident + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180511_incident_management_incidents_total_unique_counts.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.aggregated_metrics.product_analytics_test_metrics_intersection` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183205_product_analytics_test_metrics_intersection.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.aggregated_metrics.product_analytics_test_metrics_union` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183203_product_analytics_test_metrics_union.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.deployments` Total deployments count for recent 28 days -| field | value | -| --- | --- | -| `key_path` | **`counts_monthly.deployments`** | -| `product_section` | ops | -| `product_stage` | release | -| `product_group` | `group::ops release` | -| `product_category` | | -| `value_type` | number | -| `status` | data_available | -| `milestone` | 13.2 | -| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35493) | -| `time_frame` | 28d | -| `data_source` | Database | -| `distribution` | ee, ce | -| `tier` | free, premium, ultimate | - -## `database.adapter` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210201124930_deployments.yml) + +Group: `group::ops release` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts_monthly.failed_deployments` + +Total failed deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181924_failed_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.packages` + +Monthly count of Packages + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181050_packages.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.personal_snippets` + +Monthly count of Personal Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180308_personal_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts_monthly.project_snippets` + +Monthly count of Project Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180310_project_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts_monthly.projects_with_alerts_created` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183159_projects_with_alerts_created.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `counts_monthly.snippets` + +Monthly count of All Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180312_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `counts_monthly.successful_deployments` + +Total successful deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181923_successful_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `counts_weekly.aggregated_metrics.compliance_features_track_unique_visits_union` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183211_compliance_features_track_unique_visits_union.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `counts_weekly.aggregated_metrics.i_testing_paid_monthly_active_user_total` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183219_i_testing_paid_monthly_active_user_total.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `counts_weekly.aggregated_metrics.incident_management_alerts_total_unique_counts` + +Count of unique users per week to take an action on an alert + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180513_incident_management_alerts_total_unique_counts.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `counts_weekly.aggregated_metrics.incident_management_incidents_total_unique_counts` + +Count of unique users per week to take an action on an incident + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180515_incident_management_incidents_total_unique_counts.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `counts_weekly.aggregated_metrics.product_analytics_test_metrics_intersection` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183215_product_analytics_test_metrics_intersection.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `counts_weekly.aggregated_metrics.product_analytics_test_metrics_union` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183213_product_analytics_test_metrics_union.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `database.adapter` This metric only returns a value of PostgreSQL in supported versions of GitLab. It could be removed from the usage ping. Historically MySQL was also supported. -| field | value | -| --- | --- | -| `key_path` | **`database.adapter`** | -| `product_section` | enablement | -| `product_stage` | enablement | -| `product_group` | `group::enablement distribution` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | Database | -| `distribution` | ee, ce | -| `tier` | free, premium, ultimate | - -## `dependency_proxy_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210201124935_database_adapter.yml) + +Group: `group::enablement distribution` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `database.pg_system_id` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183248_pg_system_id.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `database.version` + +The version of the PostgreSQL database. + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216175609_version.yml) + +Group: `group::distribution` + +Status: `data_available` + +Tiers: `free` + +### `dependency_proxy_enabled` Whether dependency proxy is enabled -| field | value | -| --- | --- | -| `key_path` | **`dependency_proxy_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `elasticsearch_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `edition` + +Edition of GitLab such as EE, CE, Bronze, Silver, Gold + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216175604_edition.yml) + +Group: `group::distribution` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `elasticsearch_enabled` Whether Elasticsearch is enabled -| field | value | -| --- | --- | -| `key_path` | **`elasticsearch_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `gitaly.clusters` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210204124924_elasticsearch_enabled.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `g_project_management_epic_created_monthly` + +Count of MAU creating epics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210305144719_g_product_planning_epic_created_monthly.yml) + +Group: `group::product planning` + +Status: `implemented` + +Tiers: `premium`, `ultimate` + +### `g_project_management_epic_created_weekly` + +Count of WAU creating epics + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210305145820_g_product_planning_epic_created_weekly.yml) + +Group: `group::product planning` + +Status: `implemented` + +Tiers: `premium`, `ultimate` + +### `geo_enabled` + +Is Geo enabled? + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180406_geo_enabled.yml) + +Group: `group::geo` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `git.version` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216183237_version.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `gitaly.clusters` Total GitLab Managed clusters both enabled and disabled -| field | value | -| --- | --- | -| `key_path` | **`gitaly.clusters`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | number | -| `status` | data_available | -| `time_frame` | all | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `gitaly.servers` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210204124932_clusters.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `gitaly.filesystems` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183241_filesystems.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `gitaly.servers` Total Gitalty Servers -| field | value | -| --- | --- | -| `key_path` | **`gitaly.servers`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | number | -| `status` | data_available | -| `time_frame` | all | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `gitaly.version` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210204124930_servers.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `gitaly.version` Version of Gitaly -| field | value | -| --- | --- | -| `key_path` | **`gitaly.version`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `gitlab_pages.enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124928_version.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `gitlab_pages.enabled` Whether GitLab Pages is enabled -| field | value | -| --- | --- | -| `key_path` | **`gitlab_pages.enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `gitlab_pages.version` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124934_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `gitlab_pages.version` The version number of GitLab Pages -| field | value | -| --- | --- | -| `key_path` | **`gitlab_pages.version`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `gitlab_shared_runners_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124936_version.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `gitlab_shared_runners_enabled` Whether shared runners is enabled -| field | value | -| --- | --- | -| `key_path` | **`gitlab_shared_runners_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `grafana_link_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `gitpod_enabled` + +Whether gitpod is enabled in the instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180314_gitpod_enabled.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `grafana_link_enabled` Whether Grafana is enabled -| field | value | -| --- | --- | -| `key_path` | **`grafana_link_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `gravatar_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124922_grafana_link_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `gravatar_enabled` Whether gravatar is enabled -| field | value | -| --- | --- | -| `key_path` | **`gravatar_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `historical_max_users` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124904_gravatar_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `historical_max_users` The maximum active user count. Active is defined in UsersStatistics model. -| field | value | -| --- | --- | -| `key_path` | **`historical_max_users`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `hostname` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124835_historical_max_users.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `hostname` Host name of GitLab instance -| field | value | -| --- | --- | -| `key_path` | **`hostname`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ce, ee | -| `tier` | free, premium, ultimate | -| `skip_validation` | true | - -## `instance_auto_devops_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124827_hostname.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `ingress_modsecurity_enabled` + +Whether or not ModSecurity is enabled within Ingress + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216175459_ingress_modsecurity_enabled.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `installation_type` + +The installation method used to install GitLab (Omnibus, Helm, etc) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216175602_installation_type.yml) + +Group: `group::distribution` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `instance_auto_devops_enabled` Whether auto DevOps is enabled -| field | value | -| --- | --- | -| `key_path` | **`instance_auto_devops_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `ldap_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `ldap_enabled` Whether LDAP is enabled -| field | value | -| --- | --- | -| `key_path` | **`ldap_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `license_expires_at` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124906_ldap_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `license_expires_at` The date the license ends -| field | value | -| --- | --- | -| `key_path` | **`license_expires_at`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `license_id` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124847_license_expires_at.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `license_id` The ID of the license -| field | value | -| --- | --- | -| `key_path` | **`license_id`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `license_md5` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124833_license_id.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `license_md5` The license key of the GitLab instance -| field | value | -| --- | --- | -| `key_path` | **`license_md5`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | free, premium, ultimate | -| `skip_validation` | true | - -## `license_plan` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124831_license_md5.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `license_plan` The plan of the GitLab license -| field | value | -| --- | --- | -| `key_path` | **`license_plan`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `license_starts_at` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124849_license_plan.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `license_starts_at` The date the license starts -| field | value | -| --- | --- | -| `key_path` | **`license_starts_at`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `license_subscription_id` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124845_license_starts_at.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `license_subscription_id` Licese zuora_subscription_id -| field | value | -| --- | --- | -| `key_path` | **`license_subscription_id`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `license_trial` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124852_license_subscription_id.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `license_trial` Whether this is a trial license or not -| field | value | -| --- | --- | -| `key_path` | **`license_trial`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `license_trial_ends_on` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210204124851_license_trial.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `license_trial_ends_on` Date the license ends on -| field | value | -| --- | --- | -| `key_path` | **`license_trial_ends_on`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `license_user_count` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124926_license_trial_ends_on.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `license_user_count` The number of users included in the license -| field | value | -| --- | --- | -| `key_path` | **`license_user_count`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | Database | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `licensee.Company` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124843_license_user_count.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `licensee.Company` Company on the GitLab license -| field | value | -| --- | --- | -| `key_path` | **`licensee.Company`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `licensee.Email` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124841_company.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `licensee.Email` Email on the GitLab license -| field | value | -| --- | --- | -| `key_path` | **`licensee.Email`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `licensee.Name` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124839_email.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `licensee.Name` Name on the GitLab license -| field | value | -| --- | --- | -| `key_path` | **`licensee.Name`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | premium, ultimate | -| `skip_validation` | true | - -## `mattermost_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124837_name.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `mail.smtp_server` + +The value of the SMTP server that is used + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216174829_smtp_server.yml) + +Group: `group::acquisition` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `mattermost_enabled` Whether Mattermost is enabled -| field | value | -| --- | --- | -| `key_path` | **`mattermost_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `omniauth_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124908_mattermost_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `object_store.artifacts.enabled` + +Whether Object Storage is enabled for Artifacts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180836_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.artifacts.object_store.background_upload` + +Whether Background Upload for Object Storage is enabled for Artifacts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180841_background_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.artifacts.object_store.direct_upload` + +Whether Direct Upload for Object Storage is enabled for Artifacts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180840_direct_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.artifacts.object_store.enabled` + +Whether Object Storage is enabled for Artifacts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180838_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.artifacts.object_store.provider` + +What Object Storage provider has been configured for Artifacts + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180843_provider.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.external_diffs.enabled` + +Whether Object Storage is enabled for External Diffs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180845_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.external_diffs.object_store.background_upload` + +Whether Background Upload for Object Storage is enabled for External Diffs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180851_background_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.external_diffs.object_store.direct_upload` + +Whether Direct Upload for Object Storage is enabled for External Diffs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180849_direct_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.external_diffs.object_store.enabled` + +Whether Object Storage is enabled for External Diffs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180847_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.external_diffs.object_store.provider` + +What Object Storage provider has been configured for External Diffs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180852_provider.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.lfs.enabled` + +Whether Object Storage is enabled for LFS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180854_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.lfs.object_store.background_upload` + +Whether Background Upload for Object Storage is enabled for LFS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180900_background_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.lfs.object_store.direct_upload` + +Whether Direct Upload for Object Storage is enabled for LFS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180858_direct_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.lfs.object_store.enabled` + +Whether Object Storage is enabled for LFS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180856_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.lfs.object_store.provider` + +What Object Storage provider has been configured for LFS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180902_provider.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.packages.enabled` + +Whether Object Storage is enabled for Uploads + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180913_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.packages.object_store.background_upload` + +Whether Background Upload for Object Storage is enabled for Packages + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180918_background_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.packages.object_store.direct_upload` + +Whether Direct Upload for Object Storage is enabled for Packages + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180916_direct_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.packages.object_store.enabled` + +Whether Object Storage is enabled for Packages + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180915_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.packages.object_store.provider` + +What Object Storage provider has been configured for Packages + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180920_provider.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.uploads.enabled` + +Whether Object Storage is enabled for Uploads + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180903_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.uploads.object_store.background_upload` + +Whether Background Upload for Object Storage is enabled for Uploads + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180909_background_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.uploads.object_store.direct_upload` + +Whether Direct Upload for Object Storage is enabled for Uploads + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180907_direct_upload.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.uploads.object_store.enabled` + +Whether Object Storage is enabled for Uploads + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216180905_enabled.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `object_store.uploads.object_store.provider` + +What Object Storage provider has been configured for Uploads + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180911_provider.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `omniauth_enabled` Whether OmniAuth is enabled -| field | value | -| --- | --- | -| `key_path` | **`omniauth_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `prometheus_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124910_omniauth_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `prometheus_enabled` Whether the bundled Prometheus is enabled -| field | value | -| --- | --- | -| `key_path` | **`prometheus_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `prometheus_metrics_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124912_prometheus_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `prometheus_metrics_enabled` Whether Prometheus Metrics endpoint is enabled -| field | value | -| --- | --- | -| `key_path` | **`prometheus_metrics_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `recorded_at` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `recorded_at` When the Usage Ping computation was started -| field | value | -| --- | --- | -| `key_path` | **`recorded_at`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `milestone` | 8.1 | -| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557) | -| `time_frame` | none | -| `data_source` | Ruby | -| `distribution` | ee, ce | -| `tier` | free, premium, ultimate | - -## `recording_ce_finished_at` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210201124932_recorded_at.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `recording_ce_finished_at` When the core features were computed -| field | value | -| --- | --- | -| `key_path` | **`recording_ce_finished_at`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ce, ee | -| `tier` | | -| `skip_validation` | true | - -## `recording_ee_finished_at` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210204124938_recording_ce_finished_at.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `recording_ee_finished_at` When the EE-specific features were computed -| field | value | -| --- | --- | -| `key_path` | **`recording_ee_finished_at`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | ee | -| `tier` | | -| `skip_validation` | true | - -## `redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210204124940_recording_ee_finished_at.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.analytics_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175016_analytics_total_unique_counts_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.analytics_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175014_analytics_total_unique_counts_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.g_analytics_contribution_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174914_g_analytics_contribution_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.g_analytics_contribution_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174912_g_analytics_contribution_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.g_analytics_insights_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174918_g_analytics_insights_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.g_analytics_insights_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174916_g_analytics_insights_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.g_analytics_issues_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174921_g_analytics_issues_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.g_analytics_issues_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174919_g_analytics_issues_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.g_analytics_merge_request_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175004_g_analytics_merge_request_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.g_analytics_merge_request_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175002_g_analytics_merge_request_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.g_analytics_productivity_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174926_g_analytics_productivity_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.g_analytics_productivity_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174923_g_analytics_productivity_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.g_analytics_valuestream_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174929_g_analytics_valuestream_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.g_analytics_valuestream_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174927_g_analytics_valuestream_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.i_analytics_cohorts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174956_i_analytics_cohorts_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.i_analytics_cohorts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174955_i_analytics_cohorts_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.i_analytics_dev_ops_score_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175000_i_analytics_dev_ops_score_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.i_analytics_dev_ops_score_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174958_i_analytics_dev_ops_score_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.i_analytics_instance_statistics_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175012_i_analytics_instance_statistics_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.i_analytics_instance_statistics_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175010_i_analytics_instance_statistics_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.p_analytics_code_reviews_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174937_p_analytics_code_reviews_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.p_analytics_code_reviews_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174935_p_analytics_code_reviews_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.p_analytics_insights_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174945_p_analytics_insights_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.p_analytics_insights_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174943_p_analytics_insights_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.p_analytics_issues_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174949_p_analytics_issues_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.p_analytics_issues_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174947_p_analytics_issues_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.p_analytics_merge_request_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175008_p_analytics_merge_request_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.p_analytics_merge_request_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175006_p_analytics_merge_request_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.p_analytics_pipelines_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174933_p_analytics_pipelines_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.p_analytics_pipelines_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174931_p_analytics_pipelines_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.p_analytics_repo_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174953_p_analytics_repo_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.p_analytics_repo_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174951_p_analytics_repo_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.analytics.p_analytics_valuestream_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216174941_p_analytics_valuestream_monthly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.analytics.p_analytics_valuestream_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216174939_p_analytics_valuestream_weekly.yml) + +Group: `group::analytics` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_secrets_management.i_ci_secrets_management_vault_build_created_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184251_i_ci_secrets_management_vault_build_created_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_secrets_management.i_ci_secrets_management_vault_build_created_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184249_i_ci_secrets_management_vault_build_created_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.ci_templates_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.ci_templates_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_5_min_production_app_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184517_p_ci_templates_5_min_production_app_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_5_min_production_app_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184515_p_ci_templates_5_min_production_app_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_build_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184534_p_ci_templates_auto_devops_build_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_build_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184532_p_ci_templates_auto_devops_build_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_deploy_latest_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184542_p_ci_templates_auto_devops_deploy_latest_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_deploy_latest_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184540_p_ci_templates_auto_devops_deploy_latest_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_deploy_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184538_p_ci_templates_auto_devops_deploy_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_deploy_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184523_p_ci_templates_auto_devops_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_auto_devops_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184520_p_ci_templates_auto_devops_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_aws_cf_deploy_ec2_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184526_p_ci_templates_aws_cf_deploy_ec2_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_aws_cf_deploy_ec2_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184524_p_ci_templates_aws_cf_deploy_ec2_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_aws_deploy_ecs_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184530_p_ci_templates_aws_deploy_ecs_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_aws_deploy_ecs_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184528_p_ci_templates_aws_deploy_ecs_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_auto_devops_build_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184502_p_ci_templates_implicit_auto_devops_build_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_auto_devops_build_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184500_p_ci_templates_implicit_auto_devops_build_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_auto_devops_deploy_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184506_p_ci_templates_implicit_auto_devops_deploy_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_auto_devops_deploy_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184504_p_ci_templates_implicit_auto_devops_deploy_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_auto_devops_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184458_p_ci_templates_implicit_auto_devops_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_auto_devops_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184456_p_ci_templates_implicit_auto_devops_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184510_p_ci_templates_implicit_security_sast_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_security_sast_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184508_p_ci_templates_implicit_security_sast_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_security_secret_detection_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184513_p_ci_templates_implicit_security_secret_detection_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_implicit_security_secret_detection_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184512_p_ci_templates_implicit_security_secret_detection_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_security_sast_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184546_p_ci_templates_security_sast_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_security_sast_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184544_p_ci_templates_security_sast_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_security_secret_detection_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184551_p_ci_templates_security_secret_detection_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_security_secret_detection_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184549_p_ci_templates_security_secret_detection_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ci_templates.p_ci_templates_terraform_base_latest_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184555_p_ci_templates_terraform_base_latest_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ci_templates.p_ci_templates_terraform_base_latest_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184553_p_ci_templates_terraform_base_latest_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.code_review_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.code_review_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_edit_mr_desc_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184342_i_code_review_edit_mr_desc_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_edit_mr_desc_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184340_i_code_review_edit_mr_desc_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_edit_mr_title_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184338_i_code_review_edit_mr_title_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_edit_mr_title_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184336_i_code_review_edit_mr_title_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_mr_diffs_monthly` + +Count of unique merge requests per week|month with diffs viewed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175120_i_code_review_mr_diffs_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_mr_diffs_weekly` + +Count of unique merge requests per week|month with diffs viewed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175118_i_code_review_mr_diffs_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_mr_single_file_diffs_monthly` + +Count of unique merge requests per week|month with diffs viewed file by file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175128_i_code_review_mr_single_file_diffs_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_mr_single_file_diffs_weekly` + +Count of unique merge requests per week|month with diffs viewed file by file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175126_i_code_review_mr_single_file_diffs_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_add_suggestion_monthly` + +Count of unique users per month who added a suggestion + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175159_i_code_review_user_add_suggestion_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_add_suggestion_weekly` + +Count of unique users per week who added a suggestion + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175158_i_code_review_user_add_suggestion_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_apply_suggestion_monthly` + +Count of unique users per month who applied a suggestion + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175203_i_code_review_user_apply_suggestion_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_apply_suggestion_weekly` + +Count of unique users per week who applied a suggestion + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175201_i_code_review_user_apply_suggestion_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_approval_rule_added_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184434_i_code_review_user_approval_rule_added_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_approval_rule_added_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184432_i_code_review_user_approval_rule_added_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_approval_rule_deleted_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184438_i_code_review_user_approval_rule_deleted_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_approval_rule_deleted_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184436_i_code_review_user_approval_rule_deleted_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_approval_rule_edited_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184442_i_code_review_user_approval_rule_edited_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_approval_rule_edited_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184440_i_code_review_user_approval_rule_edited_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_approve_mr_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_approve_mr_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184320_i_code_review_user_approve_mr_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_assigned_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184418_i_code_review_user_assigned_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_assigned_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184416_i_code_review_user_assigned_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_assignees_changed_monthly` + +Count of unique users per month who changed assignees of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210302114145_i_code_review_user_assignees_changed_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_assignees_changed_weekly` + +Count of unique users per week who changed assignees of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302114202_i_code_review_user_assignees_changed_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_close_mr_monthly` + +Count of unique users per week|month who closed a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175136_i_code_review_user_close_mr_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_close_mr_weekly` + +Count of unique users per week|month who closed a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175134_i_code_review_user_close_mr_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_create_mr_comment_monthly` + +Count of unique users per week|month who commented on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175148_i_code_review_user_create_mr_comment_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_create_mr_comment_weekly` + +Count of unique users per week|month who commented on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175146_i_code_review_user_create_mr_comment_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_create_mr_from_issue_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184450_i_code_review_user_create_mr_from_issue_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_create_mr_from_issue_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184448_i_code_review_user_create_mr_from_issue_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_create_mr_monthly` + +Count of unique users per week|month who created a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175132_i_code_review_user_create_mr_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_create_mr_weekly` + +Count of unique users per week|month who created a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175130_i_code_review_user_create_mr_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_create_multiline_mr_comment_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184401_i_code_review_user_create_multiline_mr_comment_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_create_multiline_mr_comment_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184359_i_code_review_user_create_multiline_mr_comment_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_create_review_note_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184353_i_code_review_user_create_review_note_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_create_review_note_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184351_i_code_review_user_create_review_note_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_edit_mr_comment_monthly` + +Count of unique users per week|month who edited a comment on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175152_i_code_review_user_edit_mr_comment_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_edit_mr_comment_weekly` + +Count of unique users per week|month who edited a comment on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175150_i_code_review_user_edit_mr_comment_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_edit_multiline_mr_comment_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184405_i_code_review_user_edit_multiline_mr_comment_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_edit_multiline_mr_comment_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184403_i_code_review_user_edit_multiline_mr_comment_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_labels_changed_monthly` + +Count of unique users per month who changed labels of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210302110607_i_code_review_user_labels_changed_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_labels_changed_weekly` + +Count of unique users per week who changed labels of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302110548_i_code_review_user_labels_changed_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_marked_as_draft_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184422_i_code_review_user_marked_as_draft_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_marked_as_draft_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184420_i_code_review_user_marked_as_draft_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_merge_mr_monthly` + +Count of unique users per week|month who merged a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175144_i_code_review_user_merge_mr_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_merge_mr_weekly` + +Count of unique users per week|month who merged a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175142_i_code_review_user_merge_mr_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_milestone_changed_monthly` + +Count of unique users per month who changed milestone of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210302110520_i_code_review_user_milestone_changed_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_milestone_changed_weekly` + +Count of unique users per week who changed milestone of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302110403_i_code_review_user_milestone_changed_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_mr_discussion_locked_monthly` + +Count of unique users per month who locked a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210301103859_i_code_review_user_mr_discussion_locked_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_mr_discussion_locked_weekly` + +Count of unique users per week who locked a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302105318_i_code_review_user_mr_discussion_locked_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_mr_discussion_unlocked_monthly` + +Count of unique users per month who unlocked a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210301103925_i_code_review_user_mr_discussion_unlocked_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_mr_discussion_unlocked_weekly` + +Count of unique users per week who unlocked a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302105258_i_code_review_user_mr_discussion_unlocked_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_publish_review_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184357_i_code_review_user_publish_review_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_publish_review_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184355_i_code_review_user_publish_review_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_remove_mr_comment_monthly` + +Count of unique users per week|month who removed a comment on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175156_i_code_review_user_remove_mr_comment_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_remove_mr_comment_weekly` + +Count of unique users per week|month who removed a comment on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175154_i_code_review_user_remove_mr_comment_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_remove_multiline_mr_comment_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184409_i_code_review_user_remove_multiline_mr_comment_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_remove_multiline_mr_comment_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184407_i_code_review_user_remove_multiline_mr_comment_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_reopen_mr_monthly` + +Count of unique users per week|month who reopened a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175140_i_code_review_user_reopen_mr_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_reopen_mr_weekly` + +Count of unique users per week|month who reopened a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175138_i_code_review_user_reopen_mr_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_resolve_thread_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184330_i_code_review_user_resolve_thread_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_resolve_thread_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184328_i_code_review_user_resolve_thread_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_review_requested_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184430_i_code_review_user_review_requested_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_review_requested_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184428_i_code_review_user_review_requested_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_reviewers_changed_monthly` + +Count of unique users per month who changed reviewers of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210302114219_i_code_review_user_reviewers_changed_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_reviewers_changed_weekly` + +Count of unique users per week who changed reviewers of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302114235_i_code_review_user_reviewers_changed_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_single_file_diffs_monthly` + +Count of unique users per week|month with diffs viewed file by file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175124_i_code_review_user_single_file_diffs_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_single_file_diffs_weekly` + +Count of unique users per week|month with diffs viewed file by file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175122_i_code_review_user_single_file_diffs_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_monthly` + +Count of unique users per month who changed time estimate of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210301102134_i_code_review_user_time_estimate_changed_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_weekly` + +Count of unique users per week who changed time estimate of a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302103539_i_code_review_user_time_estimate_changed_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_time_spent_changed_monthly` + +Count of unique users per month who changed time spent on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210301102204_i_code_review_user_time_spent_changed_monthly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_time_spent_changed_weekly` + +Count of unique users per week who changed time spent on a MR + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302103615_i_code_review_user_time_spent_changed_weekly.yml) + +Group: `group::code review` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.code_review.i_code_review_user_toggled_task_item_status_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184312_i_code_review_user_toggled_task_item_status_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_toggled_task_item_status_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184310_i_code_review_user_toggled_task_item_status_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_unapprove_mr_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184326_i_code_review_user_unapprove_mr_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_unapprove_mr_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184324_i_code_review_user_unapprove_mr_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_unmarked_as_draft_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184426_i_code_review_user_unmarked_as_draft_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_unmarked_as_draft_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184424_i_code_review_user_unmarked_as_draft_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_unresolve_thread_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184334_i_code_review_user_unresolve_thread_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_unresolve_thread_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184332_i_code_review_user_unresolve_thread_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.code_review.i_code_review_user_vs_code_api_request_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184446_i_code_review_user_vs_code_api_request_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.code_review.i_code_review_user_vs_code_api_request_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184444_i_code_review_user_vs_code_api_request_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.compliance.a_compliance_audit_events_api_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183942_a_compliance_audit_events_api_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.compliance.a_compliance_audit_events_api_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183940_a_compliance_audit_events_api_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.compliance.compliance_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183946_compliance_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.compliance.compliance_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183944_compliance_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.compliance.g_compliance_audit_events_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183930_g_compliance_audit_events_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.compliance.g_compliance_audit_events_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183928_g_compliance_audit_events_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.compliance.g_compliance_dashboard_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183926_g_compliance_dashboard_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.compliance.g_compliance_dashboard_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183924_g_compliance_dashboard_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.compliance.i_compliance_audit_events_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183934_i_compliance_audit_events_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.compliance.i_compliance_audit_events_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183932_i_compliance_audit_events_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.compliance.i_compliance_credential_inventory_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183938_i_compliance_credential_inventory_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.compliance.i_compliance_credential_inventory_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183936_i_compliance_credential_inventory_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184850_deploy_token_packages_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.deploy_token_packages_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184848_deploy_token_packages_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_composer_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184806_i_package_composer_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_composer_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184805_i_package_composer_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_conan_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184810_i_package_conan_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_conan_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184808_i_package_conan_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_container_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184814_i_package_container_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_container_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184812_i_package_container_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_debian_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184818_i_package_debian_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_debian_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184816_i_package_debian_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_generic_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_generic_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184820_i_package_generic_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_golang_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184826_i_package_golang_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_golang_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184824_i_package_golang_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_maven_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184830_i_package_maven_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_maven_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184828_i_package_maven_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_npm_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184834_i_package_npm_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_npm_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184832_i_package_npm_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_nuget_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184838_i_package_nuget_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_nuget_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184836_i_package_nuget_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_pypi_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184842_i_package_pypi_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_pypi_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184840_i_package_pypi_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.deploy_token_packages.i_package_rubygems_deploy_token_monthly` + +Distinct user count events for RubyGems packages in recent 28 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303154626_i_package_rubygems_deploy_token_monthly.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.deploy_token_packages.i_package_rubygems_deploy_token_weekly` + +Distinct RubyGems pakages deployed in recent 7 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210303154624_i_package_rubygems_deploy_token_weekly.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.deploy_token_packages.i_package_tag_deploy_token_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184846_i_package_tag_deploy_token_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.deploy_token_packages.i_package_tag_deploy_token_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184844_i_package_tag_deploy_token_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184957_ecosystem_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ecosystem.ecosystem_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184955_ecosystem_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_close_issue_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184941_i_ecosystem_jira_service_close_issue_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_close_issue_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184939_i_ecosystem_jira_service_close_issue_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_create_issue_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184953_i_ecosystem_jira_service_create_issue_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_create_issue_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184951_i_ecosystem_jira_service_create_issue_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_cross_reference_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184945_i_ecosystem_jira_service_cross_reference_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_cross_reference_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184943_i_ecosystem_jira_service_cross_reference_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_list_issues_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184949_i_ecosystem_jira_service_list_issues_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ecosystem.i_ecosystem_jira_service_list_issues_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184947_i_ecosystem_jira_service_list_issues_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_confidential_issue_notification_monthly` + +Calculated unique users to trigger a Slack message by performing an action on a confidential issue by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303152233_i_ecosystem_slack_service_confidential_issue_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_confidential_issue_notification_weekly` + +Calculated unique users to trigger a Slack message by performing an action on a confidential issue by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302104814_i_ecosystem_slack_service_confidential_issue_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_confidential_note_notification_monthly` + +Calculated unique users to trigger a Slack message by creating a confidential note by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303152144_i_ecosystem_slack_service_confidential_note_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_confidential_note_notification_weekly` + +Calculated unique users to trigger a Slack message by creating a confidential note by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302104556_i_ecosystem_slack_service_confidential_note_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_deployment_notification_monthly` + +Calculated unique users to trigger a Slack message by performing a deployment by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303150912_i_ecosystem_slack_service_deployment_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_deployment_notification_weekly` + +Calculated unique users to trigger a Slack message by performing a deployment by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302103755_i_ecosystem_slack_service_deployment_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_issue_notification_monthly` + +Calculated unique users to trigger a Slack message by performing an action on an issue by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303150507_i_ecosystem_slack_service_issue_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_issue_notification_weekly` + +Calculated unique users to trigger a Slack message by performing an action on an issue by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302103002_i_ecosystem_slack_service_issue_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_merge_request_notification_monthly` + +Calculated unique users to trigger a Slack message by performing an action on a merge request by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303151831_i_ecosystem_slack_service_merge_request_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_merge_request_notification_weekly` + +Calculated unique users to trigger a Slack message by performing an action on a merge request by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302104007_i_ecosystem_slack_service_merge_request_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_note_notification_monthly` + +Calculated unique users to trigger a Slack message by creating a note by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303151946_i_ecosystem_slack_service_note_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_note_notification_weekly` + +Calculated unique users to trigger a Slack message by creating a note by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302104047_i_ecosystem_slack_service_note_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_push_notification_monthly` + +Calculated unique users to trigger a Slack message by performing a Git push by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303150654_i_ecosystem_slack_service_push_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_push_notification_weekly` + +Calculated unique users to trigger a Slack message by performing a Git push by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302103629_i_ecosystem_slack_service_push_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_tag_push_notification_monthly` + +Calculated unique users to trigger a Slack message by performing a tag push by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303152049_i_ecosystem_slack_service_tag_push_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_tag_push_notification_weekly` + +Calculated unique users to trigger a Slack message by performing a tag push by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302104144_i_ecosystem_slack_service_tag_push_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_wiki_page_notification_monthly` + +Calculated unique users to trigger a Slack message by performing an action on a wiki page by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303151609_i_ecosystem_slack_service_wiki_page_notification_monthly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ecosystem.i_ecosystem_slack_service_wiki_page_notification_weekly` + +Calculated unique users to trigger a Slack message by performing an action on a wiki page by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210302103907_i_ecosystem_slack_service_wiki_page_notification_weekly.yml) + +Group: `group::ecosystem` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.ide_edit.g_edit_by_sfe_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180334_g_edit_by_sfe_monthly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ide_edit.g_edit_by_sfe_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180332_g_edit_by_sfe_weekly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ide_edit.g_edit_by_snippet_ide_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180338_g_edit_by_snippet_ide_monthly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ide_edit.g_edit_by_snippet_ide_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180336_g_edit_by_snippet_ide_weekly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ide_edit.g_edit_by_sse_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184024_g_edit_by_sse_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ide_edit.g_edit_by_sse_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184022_g_edit_by_sse_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ide_edit.g_edit_by_web_ide_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180330_g_edit_by_web_ide_monthly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ide_edit.g_edit_by_web_ide_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180328_g_edit_by_web_ide_weekly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.ide_edit.ide_edit_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180341_ide_edit_total_unique_counts_monthly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.ide_edit.ide_edit_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180339_ide_edit_total_unique_counts_weekly.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_alert_assigned_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180533_incident_management_alert_assigned_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_alert_assigned_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180532_incident_management_alert_assigned_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_alert_status_changed_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180530_incident_management_alert_status_changed_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_alert_status_changed_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180528_incident_management_alert_status_changed_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_alert_todo_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180537_incident_management_alert_todo_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_alert_todo_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180535_incident_management_alert_todo_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_assigned_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180552_incident_management_incident_assigned_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_assigned_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180550_incident_management_incident_assigned_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_change_confidential_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180618_incident_management_incident_change_confidential_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_change_confidential_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180616_incident_management_incident_change_confidential_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_closed_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180548_incident_management_incident_closed_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_closed_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180546_incident_management_incident_closed_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_comment_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180559_incident_management_incident_comment_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_comment_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180558_incident_management_incident_comment_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_created_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180541_incident_management_incident_created_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_created_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180539_incident_management_incident_created_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_published_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180607_incident_management_incident_published_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_published_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180605_incident_management_incident_published_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_relate_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180611_incident_management_incident_relate_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_relate_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180609_incident_management_incident_relate_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_reopened_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180545_incident_management_incident_reopened_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_reopened_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180543_incident_management_incident_reopened_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_todo_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180556_incident_management_incident_todo_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_todo_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180554_incident_management_incident_todo_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_unrelate_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180614_incident_management_incident_unrelate_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_incident_unrelate_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180612_incident_management_incident_unrelate_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_zoom_meeting_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180603_incident_management_incident_zoom_meeting_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_incident_zoom_meeting_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180601_incident_management_incident_zoom_meeting_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management.incident_management_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management.incident_management_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180620_incident_management_total_unique_counts_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.incident_management_alerts.incident_management_alert_create_incident_monthly` + +Count of unique users per month to create an incident corresponding to an alert + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180625_incident_management_alert_create_incident_monthly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.incident_management_alerts.incident_management_alert_create_incident_weekly` + +Count of unique users per week to create an incident corresponding to an alert + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180623_incident_management_alert_create_incident_weekly.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_added_to_epic_monthly` + +Count of MAU adding an issue to an epic + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181414_g_project_management_issue_added_to_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_added_to_epic_weekly` + +Count of WAU adding an issue to an epic + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181413_g_project_management_issue_added_to_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_assignee_changed_monthly` + +Count of MAU changing issue assignees + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181311_g_project_management_issue_assignee_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_assignee_changed_weekly` + +Count of WAU changing issue assignees + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181310_g_project_management_issue_assignee_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_changed_epic_monthly` + +Count of MAU changing the epic on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181420_g_project_management_issue_changed_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_changed_epic_weekly` + +Count of WAU changing the epic on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181418_g_project_management_issue_changed_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_cloned_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181501_g_project_management_issue_cloned_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_cloned_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181459_g_project_management_issue_cloned_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_closed_monthly` + +Count of MAU closing an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181326_g_project_management_issue_closed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_closed_weekly` + +Count of WAU closing an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181324_g_project_management_issue_closed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_comment_added_monthly` + +Count of MAU commenting on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181446_g_project_management_issue_comment_added_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_comment_added_weekly` + +Count of WAU commenting on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181444_g_project_management_issue_comment_added_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_comment_edited_monthly` + +Count of MAU editing a comment on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181450_g_project_management_issue_comment_edited_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_comment_edited_weekly` + +Count of WAU editing a comment on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181448_g_project_management_issue_comment_edited_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_comment_removed_monthly` + +Count of MAU deleting a comment from an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181453_g_project_management_issue_comment_removed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_comment_removed_weekly` + +Count of WAU deleting a comment from an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181451_g_project_management_issue_comment_removed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_created_monthly` + +Count of MAU creating new issues + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181323_g_project_management_issue_created_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_created_weekly` + +Count of WAU creating issues + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181321_g_project_management_issue_created_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_cross_referenced_monthly` + +Count of MAU referencing an issue from somewhere else + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181348_g_project_management_issue_cross_referenced_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_cross_referenced_weekly` + +Count of WAU referncing an issue from somewhere else + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181347_g_project_management_issue_cross_referenced_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_description_changed_monthly` + +Count of MAU editing an issue description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181308_g_project_management_issue_description_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_description_changed_weekly` + +Count of WAU editing an issue description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181306_g_project_management_issue_description_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_designs_added_monthly` + +Count of MAU adding a design to an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181424_g_project_management_issue_designs_added_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_designs_added_weekly` + +Count of WAU adding a design to an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181422_g_project_management_issue_designs_added_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_designs_modified_monthly` + +Count of MAU modifying a design on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181427_g_project_management_issue_designs_modified_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_designs_modified_weekly` + +Count of WAU modifying a design on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181425_g_project_management_issue_designs_modified_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_designs_removed_monthly` + +Count of MAU removing a design from an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181431_g_project_management_issue_designs_removed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_designs_removed_weekly` + +Count of WAU removing a design from an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181429_g_project_management_issue_designs_removed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_due_date_changed_monthly` + +Count of MAU changing an issue due date + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181435_g_project_management_issue_due_date_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_due_date_changed_weekly` + +Count of WAU changing an issue due date + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181433_g_project_management_issue_due_date_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_health_status_changed_monthly` + +Count of MAU changing the health status on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181457_g_project_management_issue_health_status_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_health_status_changed_weekly` + +Count of WAU changing the health status on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181455_g_project_management_issue_health_status_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_iteration_changed_monthly` + +Count of MAU changing an issue's iteration + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181341_g_project_management_issue_iteration_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_iteration_changed_weekly` + +Count of WAU changing an issue's iteration + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181339_g_project_management_issue_iteration_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_label_changed_monthly` + +Count of MAU changing an issue's label + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181334_g_project_management_issue_label_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_label_changed_weekly` + +Count of WAU changing an issue's label + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181332_g_project_management_issue_label_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_locked_monthly` + +Count of MAU locking an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181407_g_project_management_issue_locked_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_locked_weekly` + +Count of WAU locking an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181405_g_project_management_issue_locked_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_made_confidential_monthly` + +Count of MAU making an issue confidential + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181315_g_project_management_issue_made_confidential_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_made_confidential_weekly` + +Count of WAU making an issue confidential + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181313_g_project_management_issue_made_confidential_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_made_visible_monthly` + +Count of MAU making an issue not confidential + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181319_g_project_management_issue_made_visible_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_made_visible_weekly` + +Count of WAU making an issue not confidential + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181317_g_project_management_issue_made_visible_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_marked_as_duplicate_monthly` + +Count of MAU marking an issue as a duplicate + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181403_g_project_management_issue_marked_as_duplicate_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_marked_as_duplicate_weekly` + +Count of WAU marking an issue as a duplicate + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181401_g_project_management_issue_marked_as_duplicate_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_milestone_changed_monthly` + +Count of MAU changing an issue's milestone + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_milestone_changed_weekly` + +Count of WAU changing an issue's milestone + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181336_g_project_management_issue_milestone_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_moved_monthly` + +Count of MAU moving an issue to another project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181352_g_project_management_issue_moved_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_moved_weekly` + +Count of WAU moving an issue to another project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181350_g_project_management_issue_moved_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_related_monthly` + +Count of MAU relating an issue to another issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181356_g_project_management_issue_related_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_related_weekly` + +Count of WAU relating an issue to another issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181354_g_project_management_issue_related_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_removed_from_epic_monthly` + +Count of MAU removing an issue from an epic + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181416_g_project_management_issue_removed_from_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_removed_from_epic_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184221_g_project_management_issue_removed_from_epic_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_reopened_monthly` + +Count of MAU re-opening a closed issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181330_g_project_management_issue_reopened_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_reopened_weekly` + +Count of WAU re-opening a closed issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181328_g_project_management_issue_reopened_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_time_estimate_changed_monthly` + +Count of MAU changing an issue time estimate + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181438_g_project_management_issue_time_estimate_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_time_estimate_changed_weekly` + +Count of WAU changing an issue time estimate + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181437_g_project_management_issue_time_estimate_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_time_spent_changed_monthly` + +Count of MAU recording time spent on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181442_g_project_management_issue_time_spent_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_time_spent_changed_weekly` + +Count of WAU recording time spent on an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181440_g_project_management_issue_time_spent_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_title_changed_monthly` + +Count of MAU editing an issue title + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181304_g_project_management_issue_title_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly` Distinct users count that changed issue title in a group for last recent week -| field | value | -| --- | --- | -| `key_path` | **`redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly`** | -| `product_stage` | plan | -| `product_group` | `group::project management` | -| `product_category` | issue_tracking | -| `value_type` | number | -| `status` | data_available | -| `milestone` | 13.6 | -| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/issues/229918) | -| `time_frame` | 7d | -| `data_source` | Redis_hll | -| `distribution` | ee, ce | -| `tier` | free, premium, ultimate | - -## `reply_by_email_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.issues_edit.g_project_management_issue_unlocked_monthly` + +Count of MAU marking an issue as blocked or blocked by + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181411_g_project_management_issue_unlocked_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_unlocked_weekly` + +Count of WAU marking an issue as blocked or blocked by + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181409_g_project_management_issue_unlocked_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_unrelated_monthly` + +Count of MAU unrelating an issue to another issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181400_g_project_management_issue_unrelated_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_unrelated_weekly` + +Count of WAU unrelating an issue to another issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181358_g_project_management_issue_unrelated_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.g_project_management_issue_weight_changed_monthly` + +Count of MAU changing an issue's weight + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181345_g_project_management_issue_weight_changed_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.g_project_management_issue_weight_changed_weekly` + +Count of WAU changing an issue's weight + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181343_g_project_management_issue_weight_changed_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.issues_edit.issues_edit_total_unique_counts_monthly` + +Count of MAU taking an action related to an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181504_issues_edit_total_unique_counts_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.issues_edit.issues_edit_total_unique_counts_weekly` + +Count of WAU taking an action related to an issue + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181503_issues_edit_total_unique_counts_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184301_o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly` + +Monthly unique user count having merge requests which contains the CI config file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210301144228_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_monthly.yml) + +Group: `group::pipeline authoring` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly` + +Weekly unique user count having merge requests which contains the CI config file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210301144209_o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile_weekly.yml) + +Group: `group::pipeline authoring` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.quickactions.i_quickactions_approve_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181508_i_quickactions_approve_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_approve_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181506_i_quickactions_approve_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_assign_multiple_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181516_i_quickactions_assign_multiple_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_assign_multiple_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181514_i_quickactions_assign_multiple_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_assign_reviewer_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181523_i_quickactions_assign_reviewer_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_assign_reviewer_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181521_i_quickactions_assign_reviewer_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_assign_self_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181519_i_quickactions_assign_self_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_assign_self_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181517_i_quickactions_assign_self_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_assign_single_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181512_i_quickactions_assign_single_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_assign_single_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181510_i_quickactions_assign_single_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_award_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181527_i_quickactions_award_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_award_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181525_i_quickactions_award_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_board_move_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181530_i_quickactions_board_move_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_board_move_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181529_i_quickactions_board_move_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_child_epic_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181534_i_quickactions_child_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_child_epic_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181532_i_quickactions_child_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_clear_weight_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181538_i_quickactions_clear_weight_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_clear_weight_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181536_i_quickactions_clear_weight_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_clone_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181541_i_quickactions_clone_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_clone_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181540_i_quickactions_clone_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_close_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181545_i_quickactions_close_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_close_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181543_i_quickactions_close_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_confidential_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181549_i_quickactions_confidential_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_confidential_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181547_i_quickactions_confidential_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_issue_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181556_i_quickactions_copy_metadata_issue_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_issue_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181554_i_quickactions_copy_metadata_issue_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_merge_request_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181553_i_quickactions_copy_metadata_merge_request_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_copy_metadata_merge_request_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181551_i_quickactions_copy_metadata_merge_request_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_create_merge_request_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181600_i_quickactions_create_merge_request_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_create_merge_request_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181558_i_quickactions_create_merge_request_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_done_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181604_i_quickactions_done_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_done_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181602_i_quickactions_done_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_draft_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181607_i_quickactions_draft_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_draft_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181605_i_quickactions_draft_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_due_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181611_i_quickactions_due_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_due_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181609_i_quickactions_due_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_duplicate_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181615_i_quickactions_duplicate_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_duplicate_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181613_i_quickactions_duplicate_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_epic_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181618_i_quickactions_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_epic_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181617_i_quickactions_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_estimate_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181622_i_quickactions_estimate_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_estimate_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181620_i_quickactions_estimate_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_invite_email_multiple_monthly` + +Unique users using the /invite_email quick action to add a multiple email participants to an issue within 28 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210222041235_i_quickactions_invite_email_multiple_monthly.yml) + +Group: `group::product planning` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.quickactions.i_quickactions_invite_email_multiple_weekly` + +Unique users using the /invite_email quick action to add a multiple email participants to an issue within 7 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210303154600_i_quickactions_invite_email_multiple_weekly.yml) + +Group: `group::product planning` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.quickactions.i_quickactions_invite_email_single_monthly` + +Unique users using the /invite_email quick action to add a single email participant to an issue within 28 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210222041219_i_quickactions_invite_email_single_monthly.yml) + +Group: `group::product planning` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.quickactions.i_quickactions_invite_email_single_weekly` + +Unique users using the /invite_email quick action to add a single email participant to an issue within 7 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210303154557_i_quickactions_invite_email_single_weekly.yml) + +Group: `group::product planning` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.quickactions.i_quickactions_iteration_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181626_i_quickactions_iteration_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_iteration_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181624_i_quickactions_iteration_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_label_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181629_i_quickactions_label_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_label_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181628_i_quickactions_label_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_lock_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181633_i_quickactions_lock_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_lock_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181631_i_quickactions_lock_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_merge_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181637_i_quickactions_merge_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_merge_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181635_i_quickactions_merge_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_milestone_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181641_i_quickactions_milestone_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_milestone_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181639_i_quickactions_milestone_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_move_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181644_i_quickactions_move_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_move_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181642_i_quickactions_move_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_parent_epic_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181648_i_quickactions_parent_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_parent_epic_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181646_i_quickactions_parent_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_promote_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181652_i_quickactions_promote_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_promote_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181650_i_quickactions_promote_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_publish_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181655_i_quickactions_publish_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_publish_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181654_i_quickactions_publish_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_reassign_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181659_i_quickactions_reassign_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_reassign_reviewer_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181703_i_quickactions_reassign_reviewer_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_reassign_reviewer_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181701_i_quickactions_reassign_reviewer_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_reassign_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181657_i_quickactions_reassign_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_rebase_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181707_i_quickactions_rebase_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_rebase_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181705_i_quickactions_rebase_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_relabel_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181710_i_quickactions_relabel_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_relabel_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181708_i_quickactions_relabel_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_relate_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181714_i_quickactions_relate_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_relate_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181712_i_quickactions_relate_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_child_epic_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181718_i_quickactions_remove_child_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_child_epic_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181716_i_quickactions_remove_child_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_due_date_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181721_i_quickactions_remove_due_date_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_due_date_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181719_i_quickactions_remove_due_date_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_epic_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181725_i_quickactions_remove_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_epic_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181723_i_quickactions_remove_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_estimate_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181729_i_quickactions_remove_estimate_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_estimate_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181727_i_quickactions_remove_estimate_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_iteration_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181732_i_quickactions_remove_iteration_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_iteration_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181731_i_quickactions_remove_iteration_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_milestone_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181736_i_quickactions_remove_milestone_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_milestone_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181734_i_quickactions_remove_milestone_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_parent_epic_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181740_i_quickactions_remove_parent_epic_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_parent_epic_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181738_i_quickactions_remove_parent_epic_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_time_spent_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181744_i_quickactions_remove_time_spent_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_time_spent_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181742_i_quickactions_remove_time_spent_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_remove_zoom_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181747_i_quickactions_remove_zoom_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_remove_zoom_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181745_i_quickactions_remove_zoom_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_reopen_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181751_i_quickactions_reopen_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_reopen_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181749_i_quickactions_reopen_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_shrug_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181755_i_quickactions_shrug_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_shrug_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181753_i_quickactions_shrug_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_spend_add_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181802_i_quickactions_spend_add_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_spend_add_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181800_i_quickactions_spend_add_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_spend_subtract_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181758_i_quickactions_spend_subtract_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_spend_subtract_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181756_i_quickactions_spend_subtract_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_submit_review_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181806_i_quickactions_submit_review_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_submit_review_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181804_i_quickactions_submit_review_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_subscribe_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181809_i_quickactions_subscribe_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_subscribe_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181808_i_quickactions_subscribe_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_tableflip_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181813_i_quickactions_tableflip_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_tableflip_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181811_i_quickactions_tableflip_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_tag_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181817_i_quickactions_tag_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_tag_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181815_i_quickactions_tag_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_target_branch_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181821_i_quickactions_target_branch_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_target_branch_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181819_i_quickactions_target_branch_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_title_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181824_i_quickactions_title_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_title_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181822_i_quickactions_title_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_todo_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181828_i_quickactions_todo_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_todo_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181826_i_quickactions_todo_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_unassign_all_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181835_i_quickactions_unassign_all_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_unassign_all_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181833_i_quickactions_unassign_all_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_unassign_reviewer_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181839_i_quickactions_unassign_reviewer_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_unassign_reviewer_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181837_i_quickactions_unassign_reviewer_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_unassign_specific_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181832_i_quickactions_unassign_specific_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_unassign_specific_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181830_i_quickactions_unassign_specific_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_unlabel_all_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181846_i_quickactions_unlabel_all_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_unlabel_all_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181845_i_quickactions_unlabel_all_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_unlabel_specific_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181843_i_quickactions_unlabel_specific_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_unlabel_specific_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181841_i_quickactions_unlabel_specific_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_unlock_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181850_i_quickactions_unlock_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_unlock_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181848_i_quickactions_unlock_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_unsubscribe_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181854_i_quickactions_unsubscribe_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_unsubscribe_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181852_i_quickactions_unsubscribe_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_weight_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181857_i_quickactions_weight_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_weight_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181856_i_quickactions_weight_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_wip_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181901_i_quickactions_wip_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_wip_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181859_i_quickactions_wip_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.i_quickactions_zoom_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181905_i_quickactions_zoom_monthly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.i_quickactions_zoom_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216181903_i_quickactions_zoom_weekly.yml) + +Group: `group::project management` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.quickactions.quickactions_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184803_quickactions_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.quickactions.quickactions_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184801_quickactions_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.search.i_search_advanced_monthly` + +Calculated unique users to perform Advanced searches by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180427_i_search_advanced_monthly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.search.i_search_advanced_weekly` + +Calculated unique users to perform Advanced searches by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216180425_i_search_advanced_weekly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.search.i_search_paid_monthly` + +Calculated unique users to perform a search with a paid license enabled by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216184035_i_search_paid_monthly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.search.i_search_paid_weekly` + +Calculated unique users to perform a search with a paid license enabled by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184033_i_search_paid_weekly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.search.i_search_total_monthly` + +Calculated unique users to perform Basic or Advanced searches by month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180424_i_search_total_monthly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.search.i_search_total_weekly` + +Calculated unique users to perform Basic or Advanced searches by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216180422_i_search_total_weekly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.search.search_total_unique_counts_monthly` + +Total unique users for i_search_total, i_search_advanced, i_search_paid for recent 28 days. This metric is redundant because advanced will be a subset of paid and paid will be a subset of total. i_search_total is more appropriate if you just want the total + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.search.search_total_unique_counts_weekly` + +Calculated unique users to perform Basic or Advanced searches by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.snippets.i_snippets_show_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184255_i_snippets_show_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.snippets.i_snippets_show_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184253_i_snippets_show_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.source_code.design_action_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182106_design_action_monthly.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.source_code.design_action_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182104_design_action_weekly.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.source_code.git_write_action_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184047_git_write_action_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.source_code.git_write_action_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184045_git_write_action_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.source_code.i_source_code_code_intelligence_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175117_i_source_code_code_intelligence_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.source_code.i_source_code_code_intelligence_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175114_i_source_code_code_intelligence_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.source_code.merge_request_action_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175113_merge_request_action_monthly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.source_code.merge_request_action_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216175111_merge_request_action_weekly.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.source_code.project_action_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182109_project_action_monthly.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.source_code.project_action_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182107_project_action_weekly.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.source_code.wiki_action_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182102_wiki_action_monthly.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.source_code.wiki_action_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182100_wiki_action_weekly.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.terraform.p_terraform_state_api_unique_users_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184259_p_terraform_state_api_unique_users_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.terraform.p_terraform_state_api_unique_users_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184257_p_terraform_state_api_unique_users_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.testing.i_testing_full_code_quality_report_total_monthly` + +Count of unique users per week|month who visit the full code quality report + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182147_i_testing_full_code_quality_report_total_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_full_code_quality_report_total_weekly` + +Count of unique users per week|month who visit the full code quality report + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182145_i_testing_full_code_quality_report_total_weekly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_group_code_coverage_project_click_total_monthly` + +Count of unique users per week|month who click on a project link in the group code coverage table + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182153_i_testing_group_code_coverage_project_click_total_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_group_code_coverage_project_click_total_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184132_i_testing_group_code_coverage_project_click_total_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.testing.i_testing_group_code_coverage_visit_total_monthly` + +Count of unique users per week|month who visited the group code coverage page + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182143_i_testing_group_code_coverage_visit_total_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_group_code_coverage_visit_total_weekly` + +Count of unique users per week|month who visited the group code coverage page + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182141_i_testing_group_code_coverage_visit_total_weekly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_load_performance_widget_total_monthly` + +Count of unique users per week|month who expanded the load performance report MR widget + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182156_i_testing_load_performance_widget_total_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_load_performance_widget_total_weekly` + +Count of unique users per week|month who expanded the load performance report MR widget + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182154_i_testing_load_performance_widget_total_weekly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_monthly` + +Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182200_i_testing_metrics_report_artifact_uploaders_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_metrics_report_artifact_uploaders_weekly` + +Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216182158_i_testing_metrics_report_artifact_uploaders_weekly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_metrics_report_widget_total_monthly` + +Count of unique users per week|month who expanded the metrics report MR widget + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182139_i_testing_metrics_report_widget_total_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_metrics_report_widget_total_weekly` + +Count of unique users per week|month who expanded the metrics report MR widget + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182138_i_testing_metrics_report_widget_total_weekly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_test_case_parsed_monthly` + +Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182136_i_testing_test_case_parsed_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_test_case_parsed_weekly` + +Internal Tracking to count number of unit tests parsed for planning of future code testing features. Data available [here](https://app.periscopedata.com/app/gitlab/788674/Verify:Testing-Group-Metrics?widget=10454394&udv=0) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210216182134_i_testing_test_case_parsed_weekly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_web_performance_widget_total_monthly` + +Count of unique users per week|month who expanded the browser performance report MR widget + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182151_i_testing_web_performance_widget_total_monthly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.i_testing_web_performance_widget_total_weekly` + +Count of unique users per week|month who expanded the browser performance report MR widget + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216182149_i_testing_web_performance_widget_total_weekly.yml) + +Group: `group::testing` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `redis_hll_counters.testing.testing_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184140_testing_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.testing.testing_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184138_testing_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_composer_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184854_i_package_composer_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_composer_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184852_i_package_composer_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_conan_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184858_i_package_conan_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_conan_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184856_i_package_conan_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_container_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184902_i_package_container_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_container_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184900_i_package_container_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_debian_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184906_i_package_debian_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_debian_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184904_i_package_debian_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_generic_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_generic_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_golang_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184913_i_package_golang_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_golang_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184911_i_package_golang_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_maven_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184917_i_package_maven_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_maven_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184916_i_package_maven_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_npm_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184921_i_package_npm_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_npm_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184919_i_package_npm_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_nuget_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184925_i_package_nuget_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_nuget_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184923_i_package_nuget_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_pypi_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184929_i_package_pypi_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_pypi_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184927_i_package_pypi_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.i_package_rubygems_user_monthly` + +Distinct user count events for RubyGems packages in recent 28 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210303154654_i_package_rubygems_user_monthly.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.user_packages.i_package_rubygems_user_weekly` + +Distinct user count events for RubyGems packages in recent 7 days + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_7d/20210303154652_i_package_rubygems_user_weekly.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `redis_hll_counters.user_packages.i_package_tag_user_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184933_i_package_tag_user_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.i_package_tag_user_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184931_i_package_tag_user_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `redis_hll_counters.user_packages.user_packages_total_unique_counts_monthly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `redis_hll_counters.user_packages.user_packages_total_unique_counts_weekly` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml) + +Group: `` + +Status: `data_available` + +Tiers: + +### `reply_by_email_enabled` Whether incoming email is setup -| field | value | -| --- | --- | -| `key_path` | **`reply_by_email_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `signup_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124916_reply_by_email_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` + +### `search_unique_visits.i_search_advanced` + +Calculated unique users to perform Advanced searches by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180418_i_search_advanced.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `search_unique_visits.i_search_paid` + +Calculated unique users to perform a search with a paid license enabled by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180420_i_search_paid.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `search_unique_visits.i_search_total` + +Calculated unique users to perform Basic or Advanced searches by week + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180416_i_search_total.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `search_unique_visits.search_unique_visits_for_any_target_monthly` + +Total unique users for i_search_total, i_search_advanced, i_search_paid for recent 28 days. This metric is redundant because advanced will be a subset of paid and paid will be a subset of total. i_search_total is more appropriate if you just want the total + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `search_unique_visits.search_unique_visits_for_any_target_weekly` + +Total unique users for i_search_total, i_search_advanced, i_search_paid for recent 7 days. This metric is redundant because advanced will be a subset of paid and paid will be a subset of total. i_search_total is more appropriate if you just want the total + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210216183920_search_unique_visits_for_any_target_weekly.yml) + +Group: `group::global search` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `settings.ldap_encrypted_secrets_enabled` + +Is encrypted LDAP secrets configured? + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210216175606_ldap_encrypted_secrets_enabled.yml) + +Group: `group::distribution` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `settings.operating_system` + +Information about the operating system running GitLab + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210225045628_operating_system.yml) + +Group: `group::distribution` + +Status: `implemented` + +Tiers: `free`, `premium`, `ultimate` + +### `signup_enabled` Whether public signup is enabled -| field | value | -| --- | --- | -| `key_path` | **`signup_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | - -## `uuid` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124918_signup_enabled.yml) + +Group: `group::access` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `topology.duration_s` + +Time it took to collect topology data + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180922_duration_s.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `topology.failures` + +Contains information about failed queries + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180924_failures.yml) + +Group: `group::memory` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_applications_cert_managers` + +Total GitLab Managed clusters with GitLab Managed App:Cert Manager installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175329_clusters_applications_cert_managers.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_applications_helm` + +Total GitLab Managed clusters with GitLab Managed App:Helm enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175331_clusters_applications_helm.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_applications_ingress` + +Total GitLab Managed clusters with GitLab Managed App:Ingress installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175333_clusters_applications_ingress.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_applications_knative` + +Total GitLab Managed clusters with GitLab Managed App:Knative installed + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175335_clusters_applications_knative.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_disabled` + +Total GitLab Managed disabled clusters + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175339_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_enabled` + +Total GitLab Managed clusters currently enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175341_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_management_project` + +Total GitLab Managed clusters with defined cluster management project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175337_clusters_management_project.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_platforms_eks` + +Total GitLab Managed clusters provisioned with GitLab on AWS EKS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175345_clusters_platforms_eks.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_platforms_gke` + +Total GitLab Managed clusters provisioned with GitLab on GCE GKE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175343_clusters_platforms_gke.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.clusters_platforms_user` + +Total GitLab Managed clusters that are user provisioned + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175346_clusters_platforms_user.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.group_clusters_disabled` + +Total GitLab Managed disabled clusters attached to groups + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175352_group_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.group_clusters_enabled` + +Total GitLab Managed enabled clusters attached to groups + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175354_group_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.instance_clusters_disabled` + +Total GitLab Managed disabled clusters attached to the instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175348_instance_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.instance_clusters_enabled` + +Total GitLab Managed enabled clusters attached to the instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175350_instance_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.project_clusters_disabled` + +Total GitLab Managed disabled clusters attached to projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175356_project_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.project_clusters_enabled` + +Total GitLab Managed enabled clusters attached to projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175358_project_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.configure.projects_slack_notifications_active` + +Unique projects with Slack webhook enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175400_projects_slack_notifications_active.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.configure.projects_slack_slash_active` + +Unique projects with Slack ‘/’ commands enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175402_projects_slack_slash_active.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.configure.projects_with_prometheus_alerts` + +Projects with Prometheus alerting enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175403_projects_with_prometheus_alerts.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.create.approval_project_rules` + +Number of project approval rules + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182030_approval_project_rules.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.create.approval_project_rules_with_exact_required_approvers` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183355_approval_project_rules_with_exact_required_approvers.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.approval_project_rules_with_less_approvers_than_required` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183354_approval_project_rules_with_less_approvers_than_required.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.approval_project_rules_with_more_approvers_than_required` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183352_approval_project_rules_with_more_approvers_than_required.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.approval_project_rules_with_target_branch` + +Number of project approval rules with not default target branch + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182032_approval_project_rules_with_target_branch.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.create.deploy_keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182010_deploy_keys.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182012_keys.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.merge_requests` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175045_merge_requests.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.merge_requests_with_added_rules` + +Merge Requests with added rules + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175047_merge_requests_with_added_rules.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.create.merge_requests_with_optional_codeowners` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175049_merge_requests_with_optional_codeowners.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.create.merge_requests_with_overridden_project_rules` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183339_merge_requests_with_overridden_project_rules.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.merge_requests_with_required_codeowners` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175051_merge_requests_with_required_codeowners.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.create.projects_enforcing_code_owner_approval` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182019_projects_enforcing_code_owner_approval.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.projects_imported_from_github` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180630_projects_imported_from_github.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.projects_with_disable_overriding_approvers_per_merge_request` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182014_projects_with_disable_overriding_approvers_per_merge_request.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.projects_with_repositories_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182023_projects_with_repositories_enabled.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.projects_with_sectional_code_owner_rules` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182021_projects_with_sectional_code_owner_rules.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.projects_without_disable_overriding_approvers_per_merge_request` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182015_projects_without_disable_overriding_approvers_per_merge_request.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.protected_branches` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182025_protected_branches.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.remote_mirrors` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182017_remote_mirrors.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.snippets` + +Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180316_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.create.suggestions` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175053_suggestions.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.total_number_of_locked_files` + +The total number of exclusive file locks (through the CLI) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182028_total_number_of_locked_files.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.total_number_of_path_locks` + +The total number of default branch locks done through the GitLab UI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182027_total_number_of_path_locks.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.users_using_lfs_locks` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183346_users_using_lfs_locks.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.create.users_using_path_locks` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183344_users_using_path_locks.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.bulk_imports.gitlab` + +Distinct count of users that triggered an import using the Group Migration tool + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180634_gitlab.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.bulk_imports.gitlab_v1` + +Count of imports using GitLab Migration + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180636_gitlab_v1.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.events` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180754_events.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.group_imports.gitlab_migration` + +Count of groups imported using GitLab Migration + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180703_gitlab_migration.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.group_imports.group_import` + +Count of group imports using Group Import/Export + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180702_group_import.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.group_saml_enabled` + +Has the instance enabled Group SAML SSO `https://docs.gitlab.com/ee/user/group/saml_sso/` on at least 1 group? + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180813_group_saml_enabled.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `premium` + +### `usage_activity_by_stage.manage.groups` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180756_groups.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.groups_imported` + +Distinct count of users that imported groups using Group Import + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180729_groups_imported.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issue_imports.csv` + +Count of (attempted) imports from csv files + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180700_csv.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issue_imports.fogbugz` + +Count of projects imported from fogbugz + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180656_fogbugz.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issue_imports.jira` + +Count of projects imported from Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180654_jira.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issue_imports.phabricator` + +Count of projects imported from phabricator + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180658_phabricator.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issues_imported.csv` + +Distinct count of users that imported issues into projects using CSV upload + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180727_csv.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issues_imported.fogbugz` + +Distinct count of users that imported issues into projects using FogBugz + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180724_fogbugz.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issues_imported.jira` + +Distinct count of users that imported issues into projects using Jira + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180722_jira.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.issues_imported.phabricator` + +Distinct count of users that imported issues into projects using Phabricator + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180726_phabricator.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.ldap_admin_sync_enabled` + +Has the instance configured LDAP Admin Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#administrator-sync`? + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180811_ldap_admin_sync_enabled.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.manage.ldap_group_sync_enabled` + +Has the instance configured LDAP Group Sync `https://docs.gitlab.com/ee/administration/auth/ldap/#group-sync`? + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180809_ldap_group_sync_enabled.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.manage.ldap_keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180800_ldap_keys.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.ldap_servers` + +Number of LDAP servers configured for the instance `https://docs.gitlab.com/ee/administration/auth/ldap/#multiple-ldap-servers` + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180807_ldap_servers.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.manage.ldap_users` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180801_ldap_users.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.omniauth_providers` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183400_omniauth_providers.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.bitbucket` + +Count of projects imported from Bitbucket + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180643_bitbucket.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.bitbucket_server` + +Count of projects imported from Bitbucket Server + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180645_bitbucket_server.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.git` + +Count of projects imported by URL + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180649_git.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.gitea` + +Count of projects imported from Gitea + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180647_gitea.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.github` + +Count of projects imported from GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180641_github.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.gitlab` + +Count of projects imported from GitLab.com + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180639_gitlab.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.gitlab_migration` + +Count of projects imported using GitLab Migration + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180652_gitlab_migration.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.gitlab_project` + +Count of projects imported using Project Import/Export + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180638_gitlab_project.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.project_imports.manifest` + +Count of projects imported using manifst file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180650_manifest.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.bitbucket` + +Distinct count of users that imported projects from Bitbucket Cloud + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180713_bitbucket.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.bitbucket_server` + +Distinct count of users that imported projects from Bitbucket Server + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180715_bitbucket_server.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.git` + +Distinct count of users that imported projects using Import by URL + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180718_git.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.gitea` + +Distinct count of users that imported projects from Gitea + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180716_gitea.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.github` + +Distinct count of users that imported projects from GitHub + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180711_github.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.gitlab` + +Distinct count of users that imported projects from GitLab.com + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180709_gitlab.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.gitlab_project` + +Distinct count of users that imported projects using Project Import/Export + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180707_gitlab_project.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.manifest` + +Distinct count of users that imported projects using Manifest file + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180720_manifest.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_imported.total` + +Total count of all projects imported with import_source NOT NULL + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180705_total.yml) + +Group: `group::import` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage.manage.projects_with_compliance_framework` + +Number of projects labeled with a compliance framework label [see](https://gitlab.com/gitlab-org/gitlab/-/issues/118671) + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180805_projects_with_compliance_framework.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.manage.unique_users_all_imports` + +Distinct count of users that triggered any kind of import + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180632_unique_users_all_imports.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.user_auth_by_provider.google_oauth2` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183410_google_oauth2.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.user_auth_by_provider.standard` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183408_standard.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.user_auth_by_provider.two-factor` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183402_two-factor.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.user_auth_by_provider.two-factor-via-u2f-device` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183404_two-factor-via-u2f-device.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.user_auth_by_provider.two-factor-via-webauthn-device` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183406_two-factor-via-webauthn-device.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.users_created` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180758_users_created.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.manage.value_stream_management_customized_group_stages` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180803_value_stream_management_customized_group_stages.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.monitor.clusters` + +Total GitLab Managed clusters both enabled and disabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180945_clusters.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.clusters_applications_prometheus` + +Total GitLab Managed clusters with Prometheus enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180947_clusters_applications_prometheus.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.operations_dashboard_default_dashboard` + +Active users with enabled operations dashboard + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180949_operations_dashboard_default_dashboard.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.operations_dashboard_users_with_projects_added` + +Active users with projects on operations dashboard + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180953_operations_dashboard_users_with_projects_added.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.projects_incident_sla_enabled` + +Projects where Incident SLA is enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180522_projects_incident_sla_enabled.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.projects_with_alert_incidents` + +Count of unique projects with an incident from an alert + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180520_projects_with_alert_incidents.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.projects_with_enabled_alert_integrations_histogram` + +Histogram (buckets 1 to 100) of projects with at least 1 enabled integration. + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210309165717_projects_with_enabled_alert_integrations_histogram.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.monitor.projects_with_error_tracking_enabled` + +Projects where error tracking is enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180517_projects_with_error_tracking_enabled.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.projects_with_incidents` + +Count of unique projects with an incident + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180518_projects_with_incidents.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.monitor.projects_with_tracing_enabled` + +Projects with tracing enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180951_projects_with_tracing_enabled.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.package.projects_with_packages` + +Projects with package registry configured + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181055_projects_with_packages.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.assignee_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216181132_assignee_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.plan.epics` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181134_epics.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.issues` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181115_issues.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.label_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181135_label_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.milestone_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181137_milestone_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.notes` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181117_notes.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.projects` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181119_projects.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.projects_jira_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181126_projects_jira_active.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.projects_jira_dvcs_cloud_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181128_projects_jira_dvcs_cloud_active.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.projects_jira_dvcs_server_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181130_projects_jira_dvcs_server_active.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.service_desk_enabled_projects` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181122_service_desk_enabled_projects.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.service_desk_issues` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181124_service_desk_issues.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.plan.todos` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181121_todos.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.release.deployments` + +Unique users triggering deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181926_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.release.failed_deployments` + +Total failed deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181928_failed_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.release.projects_mirrored_with_pipelines_enabled` + +Projects with repository mirroring enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181934_projects_mirrored_with_pipelines_enabled.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.release.releases` + +Unique users creating release tags + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181930_releases.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.release.successful_deployments` + +Total successful deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181932_successful_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.secure.api_fuzzing_scans` + +Counts API fuzzing jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180353_api_fuzzing_scans.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.secure.container_scanning_scans` + +Counts container scanning jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175503_container_scanning_scans.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage.secure.coverage_fuzzing_scans` + +Counts fuzzing jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216180352_coverage_fuzzing_scans.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.secure.dast_scans` + +Counts dast jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182122_dast_scans.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.secure.dependency_scanning_scans` + +Counts dependency scanning jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175220_dependency_scanning_scans.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage.secure.sast_scans` + +Counts sast jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182120_sast_scans.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.secure.secret_detection_scans` + +Counts secret detection jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216182123_secret_detection_scans.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage.secure.user_api_fuzzing_dnd_jobs` + +Count of API Fuzzing `docker-in-docker` jobs by job name + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180350_user_api_fuzzing_dnd_jobs.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.secure.user_api_fuzzing_jobs` + +Count of API Fuzzing jobs by job name + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216180348_user_api_fuzzing_jobs.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.secure.user_container_scanning_jobs` + +no idea, Count of Container Scanning jobs run, it implies user but AFAIK we don't track per user + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175501_user_container_scanning_jobs.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage.secure.user_coverage_fuzzing_jobs` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183514_user_coverage_fuzzing_jobs.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.secure.user_dast_jobs` + +Count of DAST jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175614_user_dast_jobs.yml) + +Group: `group::dynamic analysis` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.secure.user_dependency_scanning_jobs` + +no idea, Count of Dependency Scanning jobs run, it implies user but AFAIK we don't track per user + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175216_user_dependency_scanning_jobs.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage.secure.user_license_management_jobs` + +no idea, Count of License Scanning jobs run, it implies user but AFAIK we don't track per user + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210216175218_user_license_management_jobs.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage.secure.user_preferences_group_overview_security_dashboard` + +Users who set personal preference to see Details on Group overview page + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182207_user_preferences_group_overview_security_dashboard.yml) + +Group: `group::threat insights` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage.secure.user_sast_jobs` + +Count of SAST jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182116_user_sast_jobs.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.secure.user_secret_detection_jobs` + +Count of Secret Detection Jobs + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216182118_user_secret_detection_jobs.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.secure.user_unique_users_all_secure_scanners` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181954_user_unique_users_all_secure_scanners.yml) + +Group: `group::secure` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_builds` + +Unique builds in project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175525_ci_builds.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_external_pipelines` + +Total pipelines in external repositories + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175527_ci_external_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_internal_pipelines` + +Total pipelines in GitLab repositories + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175529_ci_internal_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_pipeline_config_auto_devops` + +Total pipelines from an Auto DevOps template + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175531_ci_pipeline_config_auto_devops.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_pipeline_config_repository` + +Total Pipelines from templates in repository + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175533_ci_pipeline_config_repository.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_pipeline_schedules` + +Pipeline schedules in GitLab + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175535_ci_pipeline_schedules.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_pipelines` + +Distinct Users triggering Total pipelines + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175537_ci_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.ci_triggers` + +Total configured Triggers in project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216175539_ci_triggers.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage.verify.clusters_applications_runner` + +Total GitLab Managed clusters with Runner enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216181949_clusters_applications_runner.yml) + +Group: `group::runner` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage.verify.projects_reporting_ci_cd_back_to_github` + +Projects with a GitHub service pipeline enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210216175540_projects_reporting_ci_cd_back_to_github.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_applications_cert_managers` + +Total GitLab Managed clusters with Cert Manager enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_applications_helm` + +Total GitLab Managed clusters with Helm enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_applications_ingress` + +Total GitLab Managed clusters with Ingress enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_applications_knative` + +Total GitLab Managed clusters with Knative enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_disabled` + +Total GitLab Managed disabled clusters + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175415_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_enabled` + +Total GitLab Managed clusters currently enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175417_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_management_project` + +Total GitLab Managed clusters with defined cluster management project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175413_clusters_management_project.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_platforms_eks` + +Total GitLab Managed clusters provisioned with GitLab on AWS EKS + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175420_clusters_platforms_eks.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_platforms_gke` + +Total GitLab Managed clusters provisioned with GitLab on GCE GKE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175419_clusters_platforms_gke.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.clusters_platforms_user` + +Total GitLab Managed clusters that are user provisioned + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175422_clusters_platforms_user.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.group_clusters_disabled` + +Total GitLab Managed disabled clusters attached to groups + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175428_group_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.group_clusters_enabled` + +Total GitLab Managed enabled clusters attached to groups + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175430_group_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.instance_clusters_disabled` + +Total GitLab Managed disabled clusters attached to the instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175424_instance_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.instance_clusters_enabled` + +Total GitLab Managed enabled clusters attached to the instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175426_instance_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.project_clusters_disabled` + +Total GitLab Managed disabled clusters attached to projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175432_project_clusters_disabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.project_clusters_enabled` + +Total GitLab Managed enabled clusters attached to projects + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175434_project_clusters_enabled.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.configure.projects_slack_notifications_active` + +Unique projects with Slack webhook enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175436_projects_slack_notifications_active.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.configure.projects_slack_slash_active` + +Unique projects with Slack ‘/’ commands enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175437_projects_slack_slash_active.yml) + +Group: `group::configure` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.configure.projects_with_prometheus_alerts` + +Projects with Prometheus alerting enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180955_projects_with_prometheus_alerts.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_design_management` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_git_write` + +Aggregated value for wiki, design and project repo actions + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182041_action_monthly_active_users_git_write.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_ide_edit` + +Count unique edit actions when users used an IDE, no matter which one + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_project_repo` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_sfe_edit` + +Count unique edit actions using the single file editor + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180321_action_monthly_active_users_sfe_edit.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_snippet_editor_edit` + +Count unique edit actions using the snippet editor + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180323_action_monthly_active_users_snippet_editor_edit.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_sse_edit` + +Count unique edit actions using the static site editor + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180325_action_monthly_active_users_sse_edit.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_web_ide_edit` + +Count unique edit actions using the web IDE + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180319_action_monthly_active_users_web_ide_edit.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.action_monthly_active_users_wiki_repo` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180747_action_monthly_active_users_wiki_repo.yml) + +Group: `group::knowledge` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.approval_project_rules` + +Number of project approval rules + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182056_approval_project_rules.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.create.approval_project_rules_with_exact_required_approvers` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183622_approval_project_rules_with_exact_required_approvers.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.approval_project_rules_with_less_approvers_than_required` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183620_approval_project_rules_with_less_approvers_than_required.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.approval_project_rules_with_more_approvers_than_required` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183618_approval_project_rules_with_more_approvers_than_required.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.approval_project_rules_with_target_branch` + +Number of project approval rules with not default target branch + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182058_approval_project_rules_with_target_branch.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.create.deploy_keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182034_deploy_keys.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182036_keys.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.merge_requests` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175055_merge_requests.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.merge_requests_users` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175101_merge_requests_users.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.merge_requests_with_added_rules` + +Merge Requests with added rules + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175103_merge_requests_with_added_rules.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.create.merge_requests_with_optional_codeowners` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175105_merge_requests_with_optional_codeowners.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.create.merge_requests_with_overridden_project_rules` + +Number of merge requests that have local rules that have overwritten a project rule + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182047_merge_requests_with_overridden_project_rules.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.create.merge_requests_with_required_codeowners` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175107_merge_requests_with_required_codeowners.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.create.projects_enforcing_code_owner_approval` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182043_projects_enforcing_code_owner_approval.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.projects_imported_from_github` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180731_projects_imported_from_github.yml) + +Group: `group::import` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.projects_with_disable_overriding_approvers_per_merge_request` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175057_projects_with_disable_overriding_approvers_per_merge_request.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.projects_with_repositories_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182049_projects_with_repositories_enabled.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.projects_with_sectional_code_owner_rules` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182045_projects_with_sectional_code_owner_rules.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.projects_without_disable_overriding_approvers_per_merge_request` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175059_projects_without_disable_overriding_approvers_per_merge_request.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.protected_branches` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182051_protected_branches.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.remote_mirrors` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182038_remote_mirrors.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.snippets` + +Monthly Snippets + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180317_snippets.yml) + +Group: `group::editor` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.create.suggestions` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175109_suggestions.yml) + +Group: `group::code review` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.total_number_of_locked_files` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183614_total_number_of_locked_files.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.total_number_of_path_locks` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183613_total_number_of_path_locks.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.create.users_using_lfs_locks` + +Number of users that have used default branch locks through the UI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182054_users_using_lfs_locks.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.create.users_using_path_locks` + +Number of users that have used exclusive file locks through the CLI + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216182053_users_using_path_locks.yml) + +Group: `group::source code` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.manage.bulk_imports.gitlab` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183640_gitlab.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.bulk_imports.gitlab_v1` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183642_gitlab_v1.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.events` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180814_events.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.group_imports.gitlab_migration` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183711_gitlab_migration.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.group_imports.group_import` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183709_group_import.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.group_saml_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180833_group_saml_enabled.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.manage.groups` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180816_groups.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.groups_imported` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183737_groups_imported.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issue_imports.csv` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183707_csv.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issue_imports.fogbugz` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183703_fogbugz.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issue_imports.jira` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183701_jira.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issue_imports.phabricator` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183705_phabricator.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issues_imported.csv` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183735_csv.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issues_imported.fogbugz` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183731_fogbugz.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issues_imported.jira` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183730_jira.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.issues_imported.phabricator` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183733_phabricator.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.ldap_admin_sync_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180831_ldap_admin_sync_enabled.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.manage.ldap_group_sync_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/settings/20210216180829_ldap_group_sync_enabled.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.manage.ldap_keys` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180820_ldap_keys.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.ldap_servers` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180827_ldap_servers.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.manage.ldap_users` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180822_ldap_users.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.omniauth_providers` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183627_omniauth_providers.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.bitbucket` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183650_bitbucket.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.bitbucket_server` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183652_bitbucket_server.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.git` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183655_git.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.gitea` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183653_gitea.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.github` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183648_github.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.gitlab` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183646_gitlab.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.gitlab_migration` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183659_gitlab_migration.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.gitlab_project` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183644_gitlab_project.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.project_imports.manifest` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183657_manifest.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.bitbucket` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183720_bitbucket.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.bitbucket_server` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183722_bitbucket_server.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.git` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183726_git.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.gitea` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183724_gitea.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.github` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183718_github.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.gitlab` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183716_gitlab.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.gitlab_project` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183714_gitlab_project.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.manifest` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183728_manifest.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_imported.total` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183712_total.yml) + +Group: `` + +Status: `deprecated` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.projects_with_compliance_framework` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180825_projects_with_compliance_framework.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.manage.unique_users_all_imports` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183638_unique_users_all_imports.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.google_oauth2` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183636_google_oauth2.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.standard` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183634_standard.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183629_two-factor.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor-via-u2f-device` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183631_two-factor-via-u2f-device.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.user_auth_by_provider.two-factor-via-webauthn-device` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183633_two-factor-via-webauthn-device.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.users_created` + +Number of users created in the month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180818_users_created.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.manage.value_stream_management_customized_group_stages` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180824_value_stream_management_customized_group_stages.yml) + +Group: `group::manage` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.monitor.clusters` + +Total GitLab Managed clusters both enabled and disabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180956_clusters.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.clusters_applications_prometheus` + +Total GitLab Managed clusters with Prometheus enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180958_clusters_applications_prometheus.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.operations_dashboard_default_dashboard` + +Active users with enabled operations dashboard + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181000_operations_dashboard_default_dashboard.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.operations_dashboard_users_with_projects_added` + +Active users with projects on operations dashboard + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181006_operations_dashboard_users_with_projects_added.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.projects_incident_sla_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183753_projects_incident_sla_enabled.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.projects_with_alert_incidents` + +Count of unique projects with an incident from an alert created in the last month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180526_projects_with_alert_incidents.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.projects_with_error_tracking_enabled` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181004_projects_with_error_tracking_enabled.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.projects_with_incidents` + +Count of unique projects with an incident created in the last month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180524_projects_with_incidents.yml) + +Group: `group::health` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.monitor.projects_with_tracing_enabled` + +Projects with tracing enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181002_projects_with_tracing_enabled.yml) + +Group: `group::monitor` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.package.projects_with_packages` + +Incident confidential status changed event + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181057_projects_with_packages.yml) + +Group: `group::package` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.assignee_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216181156_assignee_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: + +### `usage_activity_by_stage_monthly.plan.epics` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181158_epics.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.issues` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181139_issues.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.label_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181200_label_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.milestone_lists` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181201_milestone_lists.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.notes` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181141_notes.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.projects` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181143_projects.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.projects_jira_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181150_projects_jira_active.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.projects_jira_dvcs_cloud_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181152_projects_jira_dvcs_cloud_active.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.projects_jira_dvcs_server_active` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181154_projects_jira_dvcs_server_active.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.service_desk_enabled_projects` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181147_service_desk_enabled_projects.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.service_desk_issues` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181148_service_desk_issues.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.plan.todos` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181145_todos.yml) + +Group: `group::plan` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.release.deployments` + +Unique users triggering deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181935_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.release.failed_deployments` + +Total failed deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181937_failed_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.release.projects_mirrored_with_pipelines_enabled` + +Projects with repository mirroring enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181943_projects_mirrored_with_pipelines_enabled.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.release.releases` + +Unique users creating release tags + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181939_releases.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.release.successful_deployments` + +Total successful deployments + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181941_successful_deployments.yml) + +Group: `group::release` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.api_fuzzing_pipeline` + +Counts of Pipelines that have at least 1 API Fuzzing Testing job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180401_api_fuzzing_pipeline.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.api_fuzzing_scans` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183838_api_fuzzing_scans.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.container_scanning_pipeline` + +no idea, what is this when did it get added? guess pipelines containing a CS job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175507_container_scanning_pipeline.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.container_scanning_scans` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183830_container_scanning_scans.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.coverage_fuzzing_pipeline` + +Counts of Pipelines that have at least 1 coverage-guided Fuzz Testing job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216180359_coverage_fuzzing_pipeline.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.coverage_fuzzing_scans` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183836_coverage_fuzzing_scans.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.dast_pipeline` + +Count of pipelines that have at least 1 DAST job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175618_dast_pipeline.yml) + +Group: `group::dynamic analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.dast_scans` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183832_dast_scans.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.dependency_scanning_pipeline` + +no idea, what is this when did it get added? guess pipelines containing a DS job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175226_dependency_scanning_pipeline.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.dependency_scanning_scans` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183828_dependency_scanning_scans.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.sast_pipeline` + +Counts of Pipelines that have at least 1 SAST job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182129_sast_pipeline.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.secure.sast_scans` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183826_sast_scans.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.secret_detection_pipeline` + +Counts of Pipelines that have at least 1 Secret Detection job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182131_secret_detection_pipeline.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.secure.secret_detection_scans` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183834_secret_detection_scans.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.user_api_fuzzing_dnd_jobs` + +Count of API Fuzzing `docker-in-docker` jobs by job names + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180357_user_api_fuzzing_dnd_jobs.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.user_api_fuzzing_jobs` + +Count of API Fuzzing jobs by job name + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216180355_user_api_fuzzing_jobs.yml) + +Group: `group::fuzz testing` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.user_container_scanning_jobs` + +no idea, Count of Container Scanning jobs run, it implies user and monthly, but AFAIK we don't track per user + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175505_user_container_scanning_jobs.yml) + +Group: `group::container security` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.user_coverage_fuzzing_jobs` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216183817_user_coverage_fuzzing_jobs.yml) + +Group: `` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.user_dast_jobs` + +Users who run a DAST job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175616_user_dast_jobs.yml) + +Group: `group::dynamic analysis` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.secure.user_dependency_scanning_jobs` + +no idea, Count of Dependency Scanning jobs run, it implies user and monthly, but AFAIK we don't track per user + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175222_user_dependency_scanning_jobs.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.user_license_management_jobs` + +no idea, Count of License Scanning jobs run, it implies user and monthly, but AFAIK we don't track per user + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/license/20210216175224_user_license_management_jobs.yml) + +Group: `group::composition analysis` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.user_preferences_group_overview_security_dashboard` + +Users who set personal preference to see Security Dashboard on Group overview page + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182209_user_preferences_group_overview_security_dashboard.yml) + +Group: `group::threat insights` + +Status: `data_available` + +Tiers: `ultimate` + +### `usage_activity_by_stage_monthly.secure.user_sast_jobs` + +Users who run a SAST job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182125_user_sast_jobs.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.secure.user_secret_detection_jobs` + +Users who run a Secret Detection job + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216182127_user_secret_detection_jobs.yml) + +Group: `group::static analysis` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.secure.user_unique_users_all_secure_scanners` + +Missing description + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181956_user_unique_users_all_secure_scanners.yml) + +Group: `group::secure` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_builds` + +Unique builds in project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175542_ci_builds.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_external_pipelines` + +Total pipelines in external repositories + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175544_ci_external_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_internal_pipelines` + +Total pipelines in GitLab repositories + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_pipeline_config_auto_devops` + +Total pipelines from an Auto DevOps template + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175548_ci_pipeline_config_auto_devops.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_pipeline_config_repository` + +Total Pipelines from templates in repository + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_pipeline_schedules` + +Pipeline schedules in GitLab + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_pipelines` + + Distinct users triggering pipelines in a month + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175554_ci_pipelines.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free` + +### `usage_activity_by_stage_monthly.verify.ci_triggers` + +Total configured Triggers in project + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216175556_ci_triggers.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.verify.clusters_applications_runner` + +Total GitLab Managed clusters with Runner enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_28d/20210216181951_clusters_applications_runner.yml) + +Group: `group::runner` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `usage_activity_by_stage_monthly.verify.projects_reporting_ci_cd_back_to_github` + +Projects with a GitHub service pipeline enabled + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210216175558_projects_reporting_ci_cd_back_to_github.yml) + +Group: `group::continuous integration` + +Status: `data_available` + +Tiers: `premium`, `ultimate` + +### `uuid` GitLab instance unique identifier -| field | value | -| --- | --- | -| `key_path` | **`uuid`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | string | -| `status` | data_available | -| `milestone` | 9.1 | -| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521) | -| `time_frame` | none | -| `data_source` | Database | -| `distribution` | ee, ce | -| `tier` | free, premium, ultimate | - -## `web_ide_clientside_preview_enabled` +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210201124933_uuid.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `version` + +Version of GitLab instance + +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/20210216175601_version.yml) + +Group: `group::distribution` + +Status: `data_available` + +Tiers: `free`, `premium`, `ultimate` + +### `web_ide_clientside_preview_enabled` Whether web ide clientside preview is enabled -| field | value | -| --- | --- | -| `key_path` | **`web_ide_clientside_preview_enabled`** | -| `product_section` | growth | -| `product_stage` | growth | -| `product_group` | `group::product intelligence` | -| `product_category` | collection | -| `value_type` | boolean | -| `status` | data_available | -| `time_frame` | none | -| `data_source` | | -| `distribution` | | -| `tier` | | -| `skip_validation` | true | +[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml) + +Group: `group::product intelligence` + +Status: `data_available` + +Tiers: `free` diff --git a/doc/development/usage_ping/index.md b/doc/development/usage_ping/index.md new file mode 100644 index 00000000000..604d59f42e1 --- /dev/null +++ b/doc/development/usage_ping/index.md @@ -0,0 +1,1337 @@ +--- +stage: Growth +group: Product Intelligence +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 +--- + +# Usage Ping Guide + +> Introduced in GitLab Ultimate 11.2, more statistics. + +This guide describes Usage Ping's purpose and how it's implemented. + +For more information about Product Intelligence, see: + +- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) +- [Snowplow Guide](../snowplow.md) + +More links: + +- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/) +- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## What is Usage Ping? + +- GitLab sends a weekly payload containing usage data to GitLab Inc. Usage Ping provides high-level data to help our product, support, and sales teams. It does not send any project names, usernames, or any other specific data. The information from the usage ping is not anonymous, it is linked to the hostname of the instance. Sending usage ping is optional, and any instance can disable analytics. +- The usage data is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features in the product. In addition to counts, other facts + that help us classify and understand GitLab installations are collected. +- Usage ping is important to GitLab as we use it to calculate our Stage Monthly Active Users (SMAU) which helps us measure the success of our stages and features. +- While usage ping is enabled, GitLab gathers data from the other instances and can show usage statistics of your instance to your users. + +### Why should we enable Usage Ping? + +- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions. +- As a benefit of having the usage ping active, GitLab lets you analyze the users’ activities over time of your GitLab installation. +- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring. +- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value) +- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization? +- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes. +- Usage Ping is enabled by default. To disable it, see [Disable Usage Ping](#disable-usage-ping). + +### Limitations + +- Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events. +- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Usage Ping to track aggregated backend events on self-managed. + +## Usage Ping payload + +You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload: + +1. Navigate to **Admin Area > Settings > Metrics and profiling**. +1. Expand the **Usage statistics** section. +1. Click the **Preview payload** button. + +For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload). + +## Disable Usage Ping + +To disable Usage Ping in the GitLab UI, go to the **Settings** page of your administration panel and uncheck the **Usage Ping** checkbox. + +To disable Usage Ping and prevent it from being configured in the future through the administration panel, Omnibus installs can set the following in [`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options): + +```ruby +gitlab_rails['usage_ping_enabled'] = false +``` + +Source installations can set the following in `gitlab.yml`: + +```yaml +production: &base + # ... + gitlab: + # ... + usage_ping_enabled: false +``` + +## Usage Ping request flow + +The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, the GitLab S3 Bucket, the GitLab Snowflake Data Warehouse, and Sisense: + +```mermaid +sequenceDiagram + participant GitLab Instance + participant Versions Application + participant Licenses Application + participant Salesforce + participant S3 Bucket + participant Snowflake DW + participant Sisense Dashboards + GitLab Instance->>Versions Application: Send Usage Ping + loop Process usage data + Versions Application->>Versions Application: Parse usage data + Versions Application->>Versions Application: Write to database + Versions Application->>Versions Application: Update license ping time + end + loop Process data for Salesforce + Versions Application-xLicenses Application: Request Zuora subscription id + Licenses Application-xVersions Application: Zuora subscription id + Versions Application-xSalesforce: Request Zuora account id by Zuora subscription id + Salesforce-xVersions Application: Zuora account id + Versions Application-xSalesforce: Usage data for the Zuora account + end + Versions Application->>S3 Bucket: Export Versions database + S3 Bucket->>Snowflake DW: Import data + Snowflake DW->>Snowflake DW: Transform data using dbt + Snowflake DW->>Sisense Dashboards: Data available for querying + Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index) +``` + +## How Usage Ping works + +1. The Usage Ping [cron job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30) is set in Sidekiq to run weekly. +1. When the cron job runs, it calls [`Gitlab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22). +1. `Gitlab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls. +1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `Gitlab::UsageData.to_json`. +1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20) + If a firewall exception is needed, the required URL depends on several things. If + the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`, + the required URL is <https://version.gitlab.com/>. + +## Usage Ping Metric Life cycle + +### 1. New metrics addition + +Please follow the [Implementing Usage Ping](#implementing-usage-ping) guide. + +### 2. Existing metric change + +Because we do not control when customers update their self-managed instances of GitLab, +we **STRONGLY DISCOURAGE** changes to the logic used to calculate any metric. +Any such changes lead to inconsistent reports from multiple GitLab instances. +If there is a problem with an existing metric, it's best to deprecate the existing metric, +and use it, side by side, with the desired new metric. + +Example: +Consider following change. Before GitLab 12.6, the `example_metric` was implemented as: + +```ruby +{ + ... + example_metric: distinct_count(Project, :creator_id) +} +``` + +For GitLab 12.6, the metric was changed to filter out archived projects: + +```ruby +{ + ... + example_metric: distinct_count(Project.non_archived, :creator_id) +} +``` + +In this scenario all instances running up to GitLab 12.5 continue to report `example_metric`, +including all archived projects, while all instances running GitLab 12.6 and higher filters +out such projects. As Usage Ping data is collected from all reporting instances, the +resulting dataset includes mixed data, which distorts any following business analysis. + +The correct approach is to add a new metric for GitLab 12.6 release with updated logic: + +```ruby +{ + ... + example_metric_without_archived: distinct_count(Project.non_archived, :creator_id) +} +``` + +and update existing business analysis artefacts to use `example_metric_without_archived` instead of `example_metric` + +### 3. Metrics deprecation and removal + +The process for deprecating and removing metrics is under development. For +more information, see the following [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284637). + +## Implementing Usage Ping + +Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event +happened over time, such as how many CI pipelines have run. They are monotonic and always trend up. +Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no +general guidelines around how to collect those, due to the individual nature of that data. + +There are several types of counters which are all found in `usage_data.rb`: + +- **Ordinary Batch Counters:** Simple count of a given ActiveRecord_Relation +- **Distinct Batch Counters:** Distinct count of a given ActiveRecord_Relation in a given column +- **Sum Batch Counters:** Sum the values of a given ActiveRecord_Relation in a given column +- **Alternative Counters:** Used for settings and configurations +- **Redis Counters:** Used for in-memory counts. + +NOTE: +Only use the provided counter methods. Each counter method contains a built in fail safe to isolate each counter to avoid breaking the entire Usage Ping. + +### Why batch counting + +For large tables, PostgreSQL can take a long time to count rows due to MVCC [(Multi-version Concurrency Control)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control). Batch counting is a counting method where a single large query is broken into multiple smaller queries. For example, instead of a single query querying 1,000,000 records, with batch counting, you can execute 100 queries of 10,000 records each. Batch counting is useful for avoiding database timeouts as each batch query is significantly shorter than one single long running query. + +For GitLab.com, there are extremely large tables with 15 second query timeouts, so we use batch counting to avoid encountering timeouts. Here are the sizes of some GitLab.com tables: + +| Table | Row counts in millions | +|------------------------------|------------------------| +| `merge_request_diff_commits` | 2280 | +| `ci_build_trace_sections` | 1764 | +| `merge_request_diff_files` | 1082 | +| `events` | 514 | + +We have several batch counting methods available: + +- [Ordinary Batch Counters](#ordinary-batch-counters) +- [Distinct Batch Counters](#distinct-batch-counters) +- [Sum Batch Counters](#sum-batch-counters) +- [Estimated Batch Counters](#estimated-batch-counters) + +Batch counting requires indexes on columns to calculate max, min, and range queries. In some cases, +you may need to add a specialized index on the columns involved in a counter. + +### Ordinary Batch Counters + +Handles `ActiveRecord::StatementInvalid` error + +Simple count of a given `ActiveRecord_Relation`, does a non-distinct batch count, smartly reduces `batch_size`, and handles errors. + +Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)` + +Arguments: + +- `relation` the ActiveRecord_Relation to perform the count +- `column` the column to perform the count on, by default is the primary key +- `batch`: default `true` to use batch counting +- `start`: custom start of the batch counting to avoid complex min calculations +- `end`: custom end of the batch counting to avoid complex min calculations + +Examples: + +```ruby +count(User.active) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id)) +``` + +### Distinct Batch Counters + +Handles `ActiveRecord::StatementInvalid` error + +Distinct count of a given `ActiveRecord_Relation` on given column, a distinct batch count, smartly reduces `batch_size`, and handles errors. + +Method: `distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)` + +Arguments: + +- `relation` the ActiveRecord_Relation to perform the count +- `column` the column to perform the distinct count, by default is the primary key +- `batch`: default `true` to use batch counting +- `batch_size`: if none set it uses default value 10000 from `Gitlab::Database::BatchCounter` +- `start`: custom start of the batch counting to avoid complex min calculations +- `end`: custom end of the batch counting to avoid complex min calculations + +WARNING: +Counting over non-unique columns can lead to performance issues. Take a look at the [iterating tables in batches](../iterating_tables_in_batches.md) guide for more details. + +Examples: + +```ruby +distinct_count(::Project, :creator_id) +distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') +``` + +### Sum Batch Counters + +Handles `ActiveRecord::StatementInvalid` error + +Sum the values of a given ActiveRecord_Relation on given column and handles errors. + +Method: `sum(relation, column, batch_size: nil, start: nil, finish: nil)` + +Arguments: + +- `relation` the ActiveRecord_Relation to perform the operation +- `column` the column to sum on +- `batch_size`: if none set it uses default value 1000 from `Gitlab::Database::BatchCounter` +- `start`: custom start of the batch counting to avoid complex min calculations +- `end`: custom end of the batch counting to avoid complex min calculations + +Examples: + +```ruby +sum(JiraImportState.finished, :imported_issues_count) +``` + +### Grouping & Batch Operations + +The `count`, `distinct_count`, and `sum` batch counters can accept an `ActiveRecord::Relation` +object, which groups by a specified column. With a grouped relation, the methods do batch counting, +handle errors, and returns a hash table of key-value pairs. + +Examples: + +```ruby +count(Namespace.group(:type)) +# returns => {nil=>179, "Group"=>54} + +distinct_count(Project.group(:visibility_level), :creator_id) +# returns => {0=>1, 10=>1, 20=>11} + +sum(Issue.group(:state_id), :weight)) +# returns => {1=>3542, 2=>6820} +``` + +### Estimated Batch Counters + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233) in GitLab 13.7. + +Estimated batch counter functionality handles `ActiveRecord::StatementInvalid` errors +when used through the provided `estimate_batch_distinct_count` method. +Errors return a value of `-1`. + +WARNING: +This functionality estimates a distinct count of a specific ActiveRecord_Relation in a given column, +which uses the [HyperLogLog](http://algo.inria.fr/flajolet/Publications/FlFuGaMe07.pdf) algorithm. +As the HyperLogLog algorithm is probabilistic, the **results always include error**. +The highest encountered error rate is 4.9%. + +When correctly used, the `estimate_batch_distinct_count` method enables efficient counting over +columns that contain non-unique values, which can not be assured by other counters. + +#### estimate_batch_distinct_count method + +Method: `estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)` + +The [method](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/utils/usage_data.rb#L63) +includes the following arguments: + +- `relation`: The ActiveRecord_Relation to perform the count. +- `column`: The column to perform the distinct count. The default is the primary key. +- `batch_size`: From `Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE`. Default value: 10,000. +- `start`: The custom start of the batch count, to avoid complex minimum calculations. +- `finish`: The custom end of the batch count to avoid complex maximum calculations. + +The method includes the following prerequisites: + +1. The supplied `relation` must include the primary key defined as the numeric column. + For example: `id bigint NOT NULL`. +1. The `estimate_batch_distinct_count` can handle a joined relation. To use its ability to + count non-unique columns, the joined relation **must NOT** have a one-to-many relationship, + such as `has_many :boards`. +1. Both `start` and `finish` arguments should always represent primary key relationship values, + even if the estimated count refers to another column, for example: + + ```ruby + estimate_batch_distinct_count(::Note, :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id)) + ``` + +Examples: + +1. Simple execution of estimated batch counter, with only relation provided, + returned value represents estimated number of unique values in `id` column + (which is the primary key) of `Project` relation: + + ```ruby + estimate_batch_distinct_count(::Project) + ``` + +1. Execution of estimated batch counter, where provided relation has applied + additional filter (`.where(time_period)`), number of unique values estimated + in custom column (`:author_id`), and parameters: `start` and `finish` together + apply boundaries that defines range of provided relation to analyze: + + ```ruby + estimate_batch_distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id)) + ``` + +1. Execution of estimated batch counter with joined relation (`joins(:cluster)`), + for a custom column (`'clusters.user_id'`): + + ```ruby + estimate_batch_distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') + ``` + +When instrumenting metric with usage of estimated batch counter please add +`_estimated` suffix to its name, for example: + +```ruby + "counts": { + "ci_builds_estimated": estimate_batch_distinct_count(Ci::Build), + ... +``` + +### Redis Counters + +Handles `::Redis::CommandError` and `Gitlab::UsageDataCounters::BaseCounter::UnknownEvent` +returns -1 when a block is sent or hash with all values -1 when a `counter(Gitlab::UsageDataCounters)` is sent +different behavior due to 2 different implementations of Redis counter + +Method: `redis_usage_data(counter, &block)` + +Arguments: + +- `counter`: a counter from `Gitlab::UsageDataCounters`, that has `fallback_totals` method implemented +- or a `block`: which is evaluated + +#### Ordinary Redis Counters + +Examples of implementation: + +- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb) +- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb) + +##### UsageData API Tracking + +<!-- There's nearly identical content in `##### Adding new events`. If you fix errors here, you may need to fix the same errors in the other location. --> + +1. Track event using `UsageData` API + + Increment event count using ordinary Redis counter, for given event name. + + Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. + + API requests are protected by checking for a valid CSRF token. + + To be able to increment the values, the related feature `usage_data_<event_name>` should be enabled. + + ```plaintext + POST /usage_data/increment_counter + ``` + + | Attribute | Type | Required | Description | + | :-------- | :--- | :------- | :---------- | + | `event` | string | yes | The event name it should be tracked | + + Response + + - `200` if event was tracked + - `400 Bad request` if event parameter is missing + - `401 Unauthorized` if user is not authenticated + - `403 Forbidden` for invalid CSRF token provided + +1. Track events using JavaScript/Vue API helper which calls the API above + + Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled to be able to track events + + ```javascript + import api from '~/api'; + + api.trackRedisCounterEvent('my_already_defined_event_name'), + ``` + +#### Redis HLL Counters + +WARNING: +HyperLogLog (HLL) is a probabilistic algorithm and its **results always includes some small error**. According to [Redis documentation](https://redis.io/commands/pfcount), data from +used HLL implementation is "approximated with a standard error of 0.81%". + +With `Gitlab::UsageDataCounters::HLLRedisCounter` we have available data structures used to count unique values. + +Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PFCOUNT](https://redis.io/commands/pfcount). + +##### Adding new events + +1. Define events in [`known_events`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/). + + Example event: + + ```yaml + - name: i_compliance_credential_inventory + category: compliance + redis_slot: compliance + expiry: 42 # 6 weeks + aggregation: weekly + ``` + + Keys: + + - `name`: unique event name. + + Name format `<prefix>_<redis_slot>_name`. + + Use one of the following prefixes for the event's name: + + - `g_` for group, as an event which is tracked for group. + - `p_` for project, as an event which is tracked for project. + - `i_` for instance, as an event which is tracked for instance. + - `a_` for events encompassing all `g_`, `p_`, `i_`. + - `o_` for other. + + Consider including in the event's name the Redis slot to be able to count totals for a specific category. + + Example names: `i_compliance_credential_inventory`, `g_analytics_contribution`. + + - `category`: event category. Used for getting total counts for events in a category, for easier + access to a group of events. + - `redis_slot`: optional Redis slot; default value: event name. Used if needed to calculate totals + for a group of metrics. Ensure keys are in the same slot. For example: + `i_compliance_credential_inventory` with `redis_slot: 'compliance'` builds Redis key + `i_{compliance}_credential_inventory-2020-34`. If `redis_slot` is not defined the Redis key will + be `{i_compliance_credential_inventory}-2020-34`. + - `expiry`: expiry time in days. Default: 29 days for daily aggregation and 6 weeks for weekly + aggregation. + - `aggregation`: may be set to a `:daily` or `:weekly` key. Defines how counting data is stored in Redis. + Aggregation on a `daily` basis does not pull more fine grained data. + - `feature_flag`: optional `default_enabled: :yaml`. If no feature flag is set then the tracking is enabled. For details, see our [GitLab internal Feature flags](../feature_flags/index.md) documentation. The feature flags are owned by the group adding the event tracking. + +Use one of the following methods to track events: + +1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, if: nil)`. + + Arguments: + + - `controller_actions`: controller actions we want to track. + - `name`: event name. + - `if`: optional custom conditions, using the same format as with Rails callbacks. + + Example usage: + + ```ruby + # controller + class ProjectsController < Projects::ApplicationController + include RedisTracking + + skip_before_action :authenticate_user!, only: :show + track_redis_hll_event :index, :show, name: 'g_compliance_example_feature_visitors' + + def index + render html: 'index' + end + + def new + render html: 'new' + end + + def show + render html: 'show' + end + end + ``` + +1. Track event in API using `increment_unique_values(event_name, values)` helper method. + + To be able to track the event, Usage Ping must be enabled and the event feature `usage_data_<event_name>` must be enabled. + + Arguments: + + - `event_name`: event name. + - `values`: values counted, one value or array of values. + + Example usage: + + ```ruby + get ':id/registry/repositories' do + repositories = ContainerRepositoriesFinder.new( + user: current_user, subject: user_group + ).execute + + increment_unique_values('i_list_repositories', current_user.id) + + present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count] + end + ``` + +1. Track event using `track_usage_event(event_name, values)` in services and GraphQL + + Increment unique values count using Redis HLL, for given event name. + + Example: + + [Track usage event for incident created in service](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.8.3-ee/app/services/issues/update_service.rb#L66) + + [Track usage event for incident created in GraphQL](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.8.3-ee/app/graphql/mutations/alert_management/update_alert_status.rb#L16) + + ```ruby + track_usage_event(:incident_management_incident_created, current_user.id) + ``` + +<!-- There's nearly identical content in `##### UsageData API Tracking`. If you find / fix errors here, you may need to fix errors in that section too. --> + +1. Track event using `UsageData` API + + Increment unique users count using Redis HLL, for given event name. + + Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. + + API requests are protected by checking for a valid CSRF token. + + To increment the values, the related feature `usage_data_<event_name>` should be + set to `default_enabled: true`. For more information, see + [Feature flags in development of GitLab](../feature_flags/index.md). + + ```plaintext + POST /usage_data/increment_unique_users + ``` + + | Attribute | Type | Required | Description | + | :-------- | :--- | :------- | :---------- | + | `event` | string | yes | The event name it should be tracked | + + Response + + Return 200 if tracking failed for any reason. + + - `200` if event was tracked or any errors + - `400 Bad request` if event parameter is missing + - `401 Unauthorized` if user is not authenticated + - `403 Forbidden` for invalid CSRF token provided + +1. Track events using JavaScript/Vue API helper which calls the API above + + Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/): + + Usage Data API is behind `usage_data_api` feature flag which, as of GitLab 13.7, is + now set to `default_enabled: true`. + + Each event tracked using Usage Data API is behind a feature flag `usage_data_#{event_name}` which should be `default_enabled: true` + + ```javascript + import api from '~/api'; + + api.trackRedisHllUserEvent('my_already_defined_event_name'), + ``` + +1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date:, context: '')`. + + Arguments: + + - `event_names`: the list of event names. + - `start_date`: start date of the period for which we want to get event data. + - `end_date`: end date of the period for which we want to get event data. + - `context`: context of the event. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`. + +1. Testing tracking and getting unique events + +Trigger events in rails console by using `track_event` method + + ```ruby + Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: 1) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: [2, 3]) + ``` + +Next, get the unique events for the current week. + + ```ruby + # Get unique events for metric for current_week + Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_audit_events', + start_date: Date.current.beginning_of_week, end_date: Date.current.next_week) + ``` + +##### Recommendations + +We have the following recommendations for [Adding new events](#adding-new-events): + +- Event aggregation: weekly. +- Key expiry time: + - Daily: 29 days. + - Weekly: 42 days. +- When adding new metrics, use a [feature flag](../../operations/feature_flags.md) to control the impact. +- For feature flags triggered by another service, set `default_enabled: false`, + - Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change + +##### Enable/Disable Redis HLL tracking + +Events are tracked behind [feature flags](../feature_flags/index.md) due to concerns for Redis performance and scalability. + +For a full list of events and corresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files. + +To enable or disable tracking for specific event in <https://gitlab.com> or <https://about.staging.gitlab.com>, run commands such as the following to +[enable or disable the corresponding feature](../feature_flags/index.md). + +```shell +/chatops run feature set <feature_name> true +/chatops run feature set <feature_name> false +``` + +##### Known events are added automatically in usage data payload + +All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209). +For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable: + +- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events. +- `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#adding-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#adding-new-events) events. + +Redis HLL implementation calculates automatic total metrics, if there are more than one metric for the same category, aggregation, and Redis slot. + +- `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric. +- `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric. + +Example of `redis_hll_counters` data: + +```ruby +{:redis_hll_counters=> + {"compliance"=> + {"g_compliance_dashboard_weekly"=>0, + "g_compliance_dashboard_monthly"=>0, + "g_compliance_audit_events_weekly"=>0, + "g_compliance_audit_events_monthly"=>0, + "compliance_total_unique_counts_weekly"=>0, + "compliance_total_unique_counts_monthly"=>0}, + "analytics"=> + {"g_analytics_contribution_weekly"=>0, + "g_analytics_contribution_monthly"=>0, + "g_analytics_insights_weekly"=>0, + "g_analytics_insights_monthly"=>0, + "analytics_total_unique_counts_weekly"=>0, + "analytics_total_unique_counts_monthly"=>0}, + "ide_edit"=> + {"g_edit_by_web_ide_weekly"=>0, + "g_edit_by_web_ide_monthly"=>0, + "g_edit_by_sfe_weekly"=>0, + "g_edit_by_sfe_monthly"=>0, + "ide_edit_total_unique_counts_weekly"=>0, + "ide_edit_total_unique_counts_monthly"=>0}, + "search"=> + {"i_search_total_weekly"=>0, "i_search_total_monthly"=>0, "i_search_advanced_weekly"=>0, "i_search_advanced_monthly"=>0, "i_search_paid_weekly"=>0, "i_search_paid_monthly"=>0, "search_total_unique_counts_weekly"=>0, "search_total_unique_counts_monthly"=>0}, + "source_code"=>{"wiki_action_weekly"=>0, "wiki_action_monthly"=>0} + } +``` + +Example usage: + +```ruby +# Redis Counters +redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter) +redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] } + +# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml + +# Tracking events +Gitlab::UsageDataCounters::HLLRedisCounter.track_event('expand_vulnerabilities', values: visitor_id) + +# Get unique events for metric +redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'expand_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) } +``` + +### Alternative Counters + +Handles `StandardError` and fallbacks into -1 this way not all measures fail if we encounter one exception. +Mainly used for settings and configurations. + +Method: `alt_usage_data(value = nil, fallback: -1, &block)` + +Arguments: + +- `value`: a simple static value in which case the value is simply returned. +- or a `block`: which is evaluated +- `fallback: -1`: the common value used for any metrics that are failing. + +Usage: + +```ruby +alt_usage_data { Gitlab::VERSION } +alt_usage_data { Gitlab::CurrentSettings.uuid } +alt_usage_data(999) +``` + +### Adding counters to build new metrics + +When adding the results of two counters, use the `add` usage data method that +handles fallback values and exceptions. It also generates a valid [SQL export](#exporting-usage-ping-sql-queries-and-definitions). + +Example usage: + +```ruby +add(User.active, User.bot) +``` + +### Prometheus Queries + +In those cases where operational metrics should be part of Usage Ping, a database or Redis query is unlikely +to provide useful data. Instead, Prometheus might be more appropriate, because most GitLab architectural +components publish metrics to it that can be queried back, aggregated, and included as usage data. + +NOTE: +Prometheus as a data source for Usage Ping is currently only available for single-node Omnibus installations +that are running the [bundled Prometheus](../../administration/monitoring/prometheus/index.md) instance. + +To query Prometheus for metrics, a helper method is available to `yield` a fully configured +`PrometheusClient`, given it is available as per the note above: + +```ruby +with_prometheus_client do |client| + response = client.query('<your query>') + ... +end +``` + +Please refer to [the `PrometheusClient` definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb) +for how to use its API to query for data. + +## Developing and testing Usage Ping + +### 1. Naming and placing the metrics + +Add the metric in one of the top level keys + +- `license`: for license related metrics. +- `settings`: for settings related metrics. +- `counts_weekly`: for counters that have data for the most recent 7 days. +- `counts_monthly`: for counters that have data for the most recent 28 days. +- `counts`: for counters that have data for all time. + +### 2. Use your Rails console to manually test counters + +```ruby +# count +Gitlab::UsageData.count(User.active) +Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) + +# count distinct +Gitlab::UsageData.distinct_count(::Project, :creator_id) +Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +``` + +### 3. Generate the SQL query + +Your Rails console returns the generated SQL queries. + +Example: + +```ruby +pry(main)> Gitlab::UsageData.count(User.active) + (2.6ms) SELECT "features"."key" FROM "features" + (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000 +``` + +### 4. Optimize queries with #database-lab + +Paste the SQL query into `#database-lab` to see how the query performs at scale. + +- `#database-lab` is a Slack channel which uses a production-sized environment to test your queries. +- GitLab.com’s production database has a 15 second timeout. +- Any single query must stay below [1 second execution time](../query_performance.md#timing-guidelines-for-queries) with cold caches. +- Add a specialized index on columns involved to reduce the execution time. + +To have an understanding of the query's execution we add in the MR description the following information: + +- For counters that have a `time_period` test we add information for both cases: + - `time_period = {}` for all time periods + - `time_period = { created_at: 28.days.ago..Time.current }` for last 28 days period +- Execution plan and query time before and after optimization +- Query generated for the index and time +- Migration output for up and down execution + +We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/). For more details, see the [database review guide](../database_review.md#preparation-when-adding-or-modifying-queries). + +#### Optimization recommendations and examples + +- Use specialized indexes [example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871), [example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445). +- Use defined `start` and `finish`, and simple queries. These values can be memoized and reused, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155). +- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316). +- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000). + +### 5. Add the metric definition + +[Check Metrics Dictionary Guide](metrics_dictionary.md) + +When adding, updating, or removing metrics, please update the [Metrics Dictionary](dictionary.md). + +### 6. Add new metric to Versions Application + +Check if new metrics need to be added to the Versions Application. See `usage_data` [schema](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147) and usage data [parameters accepted](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb). Any metrics added under the `counts` key are saved in the `stats` column. + +### 7. Add the feature label + +Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature. + +### 8. Add a changelog file + +Ensure you comply with the [Changelog entries guide](../changelog.md). + +### 9. Ask for a Product Intelligence Review + +On GitLab.com, we have DangerBot setup to monitor Product Intelligence related files and DangerBot recommends a [Product Intelligence review](product_intelligence_review.md). Mention `@gitlab-org/growth/product_intelligence/engineers` in your MR for a review. + +### 10. Verify your metric + +On GitLab.com, the Product Intelligence team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "SaaS" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric. + +### Optional: Test Prometheus based Usage Ping + +If the data submitted includes metrics [queried from Prometheus](#prometheus-queries) that you would like to inspect and verify, +then you need to ensure that a Prometheus server is running locally, and that furthermore the respective GitLab components +are exporting metrics to it. If you do not need to test data coming from Prometheus, no further action +is necessary. Usage Ping should degrade gracefully in the absence of a running Prometheus server. + +There are three kinds of components that may export data to Prometheus, and which are included in Usage Ping: + +- [`node_exporter`](https://github.com/prometheus/node_exporter) - Exports node metrics from the host machine +- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter) - Exports process metrics from various GitLab components +- various GitLab services such as Sidekiq and the Rails server that export their own metrics + +#### Test with an Omnibus container + +This is the recommended approach to test Prometheus based Usage Ping. + +The easiest way to verify your changes is to build a new Omnibus image from your code branch by using CI, then download the image +and run a local container instance: + +1. From your merge request, click on the `qa` stage, then trigger the `package-and-qa` job. This job triggers an Omnibus +build in a [downstream pipeline of the `omnibus-gitlab-mirror` project](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines). +1. In the downstream pipeline, wait for the `gitlab-docker` job to finish. +1. Open the job logs and locate the full container name including the version. It takes the following form: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`. +1. On your local machine, make sure you are signed in to the GitLab Docker registry. You can find the instructions for this in +[Authenticate to the GitLab Container Registry](../../user/packages/container_registry/index.md#authenticate-with-the-container-registry). +1. Once signed in, download the new image by using `docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` +1. For more information about working with and running Omnibus GitLab containers in Docker, please refer to [GitLab Docker images](https://docs.gitlab.com/omnibus/docker/README.html) in the Omnibus documentation. + +#### Test with GitLab development toolkits + +This is the less recommended approach, because it comes with a number of difficulties when emulating a real GitLab deployment. + +The [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) is not set up to run a Prometheus server or `node_exporter` alongside other GitLab components. If you would +like to do so, [Monitoring the GDK with Prometheus](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) is a good start. + +The [GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit) has limited support for testing Prometheus based Usage Ping. +By default, it already comes with a fully configured Prometheus service that is set up to scrape a number of components, +but with the following limitations: + +- It does not run a `gitlab-exporter` instance, so several `process_*` metrics from services such as Gitaly may be missing. +- While it runs a `node_exporter`, `docker-compose` services emulate hosts, meaning that it would normally report itself to not be associated +with any of the other services that are running. That is not how node metrics are reported in a production setup, where `node_exporter` +always runs as a process alongside other GitLab components on any given node. From Usage Ping's perspective none of the node data would therefore +appear to be associated to any of the services running, because they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Usage Ping. + +## Aggregated metrics + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6. + +WARNING: +This feature is intended solely for internal GitLab use. + +To add data for aggregated metrics into Usage Ping payload you should add corresponding definition at [`lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/) for metrics available at Community Edition and at [`ee/lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/usage_data_counters/aggregated_metrics/) for Enterprise Edition ones. + +Each aggregate definition includes following parts: + +- `name`: Unique name under which the aggregate metric is added to the Usage Ping payload. +- `operator`: Operator that defines how the aggregated metric data is counted. Available operators are: + - `OR`: Removes duplicates and counts all entries that triggered any of listed events. + - `AND`: Removes duplicates and counts all elements that were observed triggering all of following events. +- `time_frame`: One or more valid time frames. Use these to limit the data included in aggregated metric to events within a specific date-range. Valid time frames are: + - `7d`: Last seven days of data. + - `28d`: Last twenty eight days of data. + - `all`: All historical data, only available for `database` sourced aggregated metrics. +- `source`: Data source used to collect all events data included in aggregated metric. Valid data sources are: + - [`database`](#database-sourced-aggregated-metrics) + - [`redis`](#redis-sourced-aggregated-metrics) +- `events`: list of events names to aggregate into metric. All events in this list must + relay on the same data source. Additional data source requirements are described in the + [Database sourced aggregated metrics](#database-sourced-aggregated-metrics) and + [Redis sourced aggregated metrics](#redis-sourced-aggregated-metrics) sections. +- `feature_flag`: Name of [development feature flag](../feature_flags/index.md#development-type) + that is checked before metrics aggregation is performed. Corresponding feature flag + should have `default_enabled` attribute set to `false`. The `feature_flag` attribute + is optional and can be omitted. When `feature_flag` is missing, no feature flag is checked. + +Example aggregated metric entries: + +```yaml +- name: example_metrics_union + operator: OR + events: ['i_search_total', 'i_search_advanced', 'i_search_paid'] + source: redis + time_frame: + - 7d + - 28d +- name: example_metrics_intersection + operator: AND + source: database + time_frame: + - 28d + - all + events: ['dependency_scanning_pipeline_all_time', 'container_scanning_pipeline_all_time'] + feature_flag: example_aggregated_metric +``` + +Aggregated metrics collected in `7d` and `28d` time frames are added into Usage Ping payload under the `aggregated_metrics` sub-key in the `counts_weekly` and `counts_monthly` top level keys. + +```ruby +{ + :counts_monthly => { + :deployments => 1003, + :successful_deployments => 78, + :failed_deployments => 275, + :packages => 155, + :personal_snippets => 2106, + :project_snippets => 407, + :promoted_issues => 719, + :aggregated_metrics => { + :example_metrics_union => 7, + :example_metrics_intersection => 2 + }, + :snippets => 2513 + } +} +``` + +Aggregated metrics for `all` time frame are present in the `count` top level key, with the `aggregate_` prefix added to their name. + +For example: + +`example_metrics_intersection` + +Becomes: + +`counts.aggregate_example_metrics_intersection` + +```ruby +{ + :counts => { + :deployments => 11003, + :successful_deployments => 178, + :failed_deployments => 1275, + :aggregate_example_metrics_intersection => 12 + } +} +``` + +### Redis sourced aggregated metrics + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6. + +To declare the aggregate of events collected with [Redis HLL Counters](#redis-hll-counters), +you must fulfill the following requirements: + +1. All events listed at `events` attribute must come from + [`known_events/*.yml`](#known-events-are-added-automatically-in-usage-data-payload) files. +1. All events listed at `events` attribute must have the same `redis_slot` attribute. +1. All events listed at `events` attribute must have the same `aggregation` attribute. +1. `time_frame` does not include `all` value, which is unavailable for Redis sourced aggregated metrics. + +### Database sourced aggregated metrics + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52784) in GitLab 13.9. +> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. +> - It's enabled on GitLab.com. + +To declare an aggregate of metrics based on events collected from database, follow +these steps: + +1. [Persist the metrics for aggregation](#persist-metrics-for-aggregation). +1. [Add new aggregated metric definition](#add-new-aggregated-metric-definition). + +#### Persist metrics for aggregation + +Only metrics calculated with [Estimated Batch Counters](#estimated-batch-counters) +can be persisted for database sourced aggregated metrics. To persist a metric, +inject a Ruby block into the +[estimate_batch_distinct_count](#estimate_batch_distinct_count-method) method. +This block should invoke the +`Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll.save_aggregated_metrics` +[method](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb#L21), +which stores `estimate_batch_distinct_count` results for future use in aggregated metrics. + +The `Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll.save_aggregated_metrics` +method accepts the following arguments: + +- `metric_name`: The name of metric to use for aggregations. Should be the same + as the key under which the metric is added into Usage Ping. +- `recorded_at_timestamp`: The timestamp representing the moment when a given + Usage Ping payload was collected. You should use the convenience method `recorded_at` + to fill `recorded_at_timestamp` argument, like this: `recorded_at_timestamp: recorded_at` +- `time_period`: The time period used to build the `relation` argument passed into + `estimate_batch_distinct_count`. To collect the metric with all available historical + data, set a `nil` value as time period: `time_period: nil`. +- `data`: HyperLogLog buckets structure representing unique entries in `relation`. + The `estimate_batch_distinct_count` method always passes the correct argument + into the block, so `data` argument must always have a value equal to block argument, + like this: `data: result` + +Example metrics persistence: + +```ruby +class UsageData + def count_secure_pipelines(time_period) + ... + relation = ::Security::Scan.latest_successful_by_build.by_scan_types(scan_type).where(security_scans: time_period) + + pipelines_with_secure_jobs['dependency_scanning_pipeline'] = estimate_batch_distinct_count(relation, :commit_id, batch_size: 1000, start: start_id, finish: finish_id) do |result| + ::Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll + .save_aggregated_metrics(metric_name: 'dependency_scanning_pipeline', recorded_at_timestamp: recorded_at, time_period: time_period, data: result) + end + end +end +``` + +#### Add new aggregated metric definition + +After all metrics are persisted, you can add an aggregated metric definition at +[`aggregated_metrics/`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/). + +To declare the aggregate of metrics collected with [Estimated Batch Counters](#estimated-batch-counters), +you must fulfill the following requirements: + +- Metrics names listed in the `events:` attribute, have to use the same names you passed in the `metric_name` argument while persisting metrics in previous step. +- Every metric listed in the `events:` attribute, has to be persisted for **every** selected `time_frame:` value. + +Example definition: + +```yaml +- name: example_metrics_intersection_database_sourced + operator: AND + source: database + events: ['dependency_scanning_pipeline', 'container_scanning_pipeline'] + time_frame: + - 28d + - all +``` + +## Example Usage Ping payload + +The following is example content of the Usage Ping payload. + +```json +{ + "uuid": "0000000-0000-0000-0000-000000000000", + "hostname": "example.com", + "version": "12.10.0-pre", + "installation_type": "omnibus-gitlab", + "active_user_count": 999, + "recorded_at": "2020-04-17T07:43:54.162+00:00", + "edition": "EEU", + "license_md5": "00000000000000000000000000000000", + "license_id": null, + "historical_max_users": 999, + "licensee": { + "Name": "ABC, Inc.", + "Email": "email@example.com", + "Company": "ABC, Inc." + }, + "license_user_count": 999, + "license_starts_at": "2020-01-01", + "license_expires_at": "2021-01-01", + "license_plan": "ultimate", + "license_add_ons": { + }, + "license_trial": false, + "counts": { + "assignee_lists": 999, + "boards": 999, + "ci_builds": 999, + ... + }, + "container_registry_enabled": true, + "dependency_proxy_enabled": false, + "gitlab_shared_runners_enabled": true, + "gravatar_enabled": true, + "influxdb_metrics_enabled": true, + "ldap_enabled": false, + "mattermost_enabled": false, + "omniauth_enabled": true, + "prometheus_enabled": false, + "prometheus_metrics_enabled": false, + "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com", + "signup_enabled": true, + "web_ide_clientside_preview_enabled": true, + "ingress_modsecurity_enabled": true, + "projects_with_expiration_policy_disabled": 999, + "projects_with_expiration_policy_enabled": 999, + ... + "elasticsearch_enabled": true, + "license_trial_ends_on": null, + "geo_enabled": false, + "git": { + "version": { + "major": 2, + "minor": 26, + "patch": 1 + } + }, + "gitaly": { + "version": "12.10.0-rc1-93-g40980d40", + "servers": 56, + "clusters": 14, + "filesystems": [ + "EXT_2_3_4" + ] + }, + "gitlab_pages": { + "enabled": true, + "version": "1.17.0" + }, + "container_registry_server": { + "vendor": "gitlab", + "version": "2.9.1-gitlab" + }, + "database": { + "adapter": "postgresql", + "version": "9.6.15", + "pg_system_id": 6842684531675334351 + }, + "analytics_unique_visits": { + "g_analytics_contribution": 999, + ... + }, + "usage_activity_by_stage": { + "configure": { + "project_clusters_enabled": 999, + ... + }, + "create": { + "merge_requests": 999, + ... + }, + "manage": { + "events": 999, + ... + }, + "monitor": { + "clusters": 999, + ... + }, + "package": { + "projects_with_packages": 999 + }, + "plan": { + "issues": 999, + ... + }, + "release": { + "deployments": 999, + ... + }, + "secure": { + "user_container_scanning_jobs": 999, + ... + }, + "verify": { + "ci_builds": 999, + ... + } + }, + "usage_activity_by_stage_monthly": { + "configure": { + "project_clusters_enabled": 999, + ... + }, + "create": { + "merge_requests": 999, + ... + }, + "manage": { + "events": 999, + ... + }, + "monitor": { + "clusters": 999, + ... + }, + "package": { + "projects_with_packages": 999 + }, + "plan": { + "issues": 999, + ... + }, + "release": { + "deployments": 999, + ... + }, + "secure": { + "user_container_scanning_jobs": 999, + ... + }, + "verify": { + "ci_builds": 999, + ... + } + }, + "topology": { + "duration_s": 0.013836685999194742, + "application_requests_per_hour": 4224, + "query_apdex_weekly_average": 0.996, + "failures": [], + "nodes": [ + { + "node_memory_total_bytes": 33269903360, + "node_memory_utilization": 0.35, + "node_cpus": 16, + "node_cpu_utilization": 0.2, + "node_uname_info": { + "machine": "x86_64", + "sysname": "Linux", + "release": "4.19.76-linuxkit" + }, + "node_services": [ + { + "name": "web", + "process_count": 16, + "process_memory_pss": 233349888, + "process_memory_rss": 788220927, + "process_memory_uss": 195295487, + "server": "puma" + }, + { + "name": "sidekiq", + "process_count": 1, + "process_memory_pss": 734080000, + "process_memory_rss": 750051328, + "process_memory_uss": 731533312 + }, + ... + ], + ... + }, + ... + ] + } +} +``` + +## Notable changes + +In GitLab 13.5, `pg_system_id` was added to send the [PostgreSQL system identifier](https://www.2ndquadrant.com/en/blog/support-for-postgresqls-system-identifier-in-barman/). + +## Exporting Usage Ping SQL queries and definitions + +Two Rake tasks exist to export Usage Ping definitions. + +- The Rake tasks export the raw SQL queries for `count`, `distinct_count`, `sum`. +- The Rake tasks export the Redis counter class or the line of the Redis block for `redis_usage_data`. +- The Rake tasks calculate the `alt_usage_data` metrics. + +In the home directory of your local GitLab installation run the following Rake tasks for the YAML and JSON versions respectively: + +```shell +# for YAML export +bin/rake gitlab:usage_data:dump_sql_in_yaml + +# for JSON export +bin/rake gitlab:usage_data:dump_sql_in_json + +# You may pipe the output into a file +bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml +``` + +## Generating and troubleshooting usage ping + +To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping). diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md index 406a223b204..3c08fb0cc87 100644 --- a/doc/development/usage_ping/metrics_dictionary.md +++ b/doc/development/usage_ping/metrics_dictionary.md @@ -28,20 +28,22 @@ Each metric is defined in a separate YAML file consisting of a number of fields: |---------------------|----------|----------------------------------------------------------------| | `key_path` | yes | JSON key path for the metric, location in Usage Ping payload. | | `description` | yes | | -| `value_type` | yes | | -| `status` | yes | | -| `product_group` | yes | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the metric. | -| `time_frame` | yes | `string`; may be set to a value like "7d" | -| `data_source` | yes | `string`: may be set to a value like `database` or `redis_hll`. | -| `distribution` | yes | The [distribution](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/#definitions) where the metric applies. | -| `tier` | yes | The [tier]( https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/) where the metric applies. | -| `product_category` | no | The [product category](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml) for the metric. | +| `product_section` | yes | The [section](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/sections.yml). | | `product_stage` | no | The [stage](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) for the metric. | +| `product_group` | yes | The [group](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) that owns the metric. | +| `product_category` | no | The [product category](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml) for the metric. | +| `value_type` | yes | `string`; one of `string`, `number`, `boolean`, `object`. | +| `status` | yes | `string`; status of the metric, may be set to `data_available`, `planned`, `in_progress`, `implemented`, `not_used`, `deprecated` | +| `time_frame` | yes | `string`; may be set to a value like `7d`, `28d`, `all`, `none`. | +| `data_source` | yes | `string`; may be set to a value like `database`, `redis`, `redis_hll`, `prometheus`, `ruby`. | +| `distribution` | yes | `array`; may be set to one of `ce, ee` or `ee`. The [distribution](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/#definitions) where the tracked feature is available. | +| `tier` | yes | `array`; may be set to one of `free, premium, ultimate`, `premium, ultimate` or `ultimate`. The [tier]( https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/) where the tracked feature is available. | | `milestone` | no | The milestone when the metric is introduced. | | `milestone_removed` | no | The milestone when the metric is removed. | | `introduced_by_url` | no | The URL to the Merge Request that introduced the metric. | +| `skip_validation` | no | This should **not** be set. [Used for imported metrics until we review, update and make them valid](https://gitlab.com/groups/gitlab-org/-/epics/5425). | -### Example metric definition +### Example YAML metric definition The linked [`uuid`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/uuid.yml) YAML file includes an example metric definition, where the `uuid` metric is the GitLab @@ -50,18 +52,19 @@ instance unique identifier. ```yaml key_path: uuid description: GitLab instance unique identifier -value_type: string product_category: collection +product_section: growth product_stage: growth +product_group: group::product intelligence +value_type: string status: data_available milestone: 9.1 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521 -product_group: group::product intelligence time_frame: none data_source: database distribution: -- ee - ce +- ee tier: - free - premium @@ -91,3 +94,9 @@ To create a metric definition used in EE, add the `--ee` flag. bundle exec rails generate gitlab:usage_metric_definition counts.issues --ee --dir=7d create ee/config/metrics/counts_7d/issues.yml ``` + +## Metrics added dynamic to Usage Ping payload + +The [Redis HLL metrics](index.md#known-events-are-added-automatically-in-usage-data-payload) are added automatically to Usage Ping payload. + +A YAML metric definition is required for each metric. diff --git a/doc/development/usage_ping/product_intelligence_review.md b/doc/development/usage_ping/product_intelligence_review.md new file mode 100644 index 00000000000..c667bc8354c --- /dev/null +++ b/doc/development/usage_ping/product_intelligence_review.md @@ -0,0 +1,80 @@ +--- +stage: Growth +group: Product Intelligence +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 +--- + +# Product Intelligence review guidelines + +This page includes introductory material for a +[Product Intelligence](https://about.gitlab.com/handbook/engineering/development/growth/product-intelligence/) +review, and is specific to Product Intelligence reviews. For broader advice and +general best practices for code reviews, refer to our [code review guide](../code_review.md). + +## Resources for Product Intelligence reviewers + +- [Usage Ping Guide](index.md) +- [Snowplow Guide](../snowplow.md) +- [Metrics Dictionary](metrics_dictionary.md) + +## Review process + +We recommend a Product Intelligence review when an application update touches +Product Intelligence files. + +- Changes that touch `usage_data*` files. +- Changes to the Metrics Dictionary including files in: + - [`config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/metrics). + - [`ee/config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/config/metrics). + - [`dictionary.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/usage_ping/dictionary.md). + - [`schema.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/schema.json). +- Changes to `tracking` files. +- Changes to Product Intelligence tooling. For example, + [`Gitlab::UsageMetricDefinitionGenerator`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/generators/gitlab/usage_metric_definition_generator.rb) + +### Roles and process + +The merge request **author** should: + +- Decide whether a Product Intelligence review is needed. +- If a Product Intelligence review is needed, add the labels + `~product intelligence` and `~product intelligence::review pending`. +- Assign an + [engineer](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) from the Product Intelligence team for a review. +- Set the correct attributes in YAML metrics: + - `product_section`, `product_stage`, `product_group`, `product_category` + - Provide a clear description of the metric. +- Update the + [Metrics Dictionary](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/usage_ping/dictionary.md) if it is needed. +- Add a changelog [according to guidelines](../changelog.md). + +The Product Intelligence **reviewer** should: + +- Perform a first-pass review on the merge request and suggest improvements to the author. +- Approve the MR, and relabel the MR with `~"product intelligence::approved"`. + +## Review workload distribution + +[Danger bot](../dangerbot.md) adds the list of Product Intelligence changed files +and pings the +[`@gitlab-org/growth/product-intelligence/engineers`](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) group for merge requests +that are not drafts. + +Any of the Product Intelligence engineers can be assigned for the Product Intelligence review. + +### How to review for Product Intelligence + +- Check the [metrics location](index.md#1-naming-and-placing-the-metrics) in + the Usage Ping JSON payload. +- Add `~database` label and ask for [database review](../database_review.md) for + metrics that are based on Database. +- For tracking using Redis HLL (HyperLogLog): + - Check the Redis slot. + - Check if a [feature flag is needed](index.md#recommendations). +- Metrics YAML definitions: + - Check the metric `description`. + - Check the metrics `key_path`. + - Check the `product_section`, `product_stage`, `product_group`, `product_category`. + Read the [stages file](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml). + - Check the file location. Consider the time frame, and if the file should be under `ee`. + - Check the tiers. diff --git a/doc/development/value_stream_analytics.md b/doc/development/value_stream_analytics.md index b3692bd1d2c..6b2442f1c32 100644 --- a/doc/development/value_stream_analytics.md +++ b/doc/development/value_stream_analytics.md @@ -90,7 +90,7 @@ Some start/end event pairs are not "compatible" with each other. For example: - "Issue closed" to "Issue closed": Duration is always 0. The `StageEvents` module describes the allowed `start_event` and `end_event` pairings (`PAIRING_RULES` constant). If a new event is added, it needs to be registered in this module. -To add a new event: +To add a new event: 1. Add an entry in `ENUM_MAPPING` with a unique number, which is used in the `Stage` model as `enum`. 1. Define which events are compatible with the event in the `PAIRING_RULES` hash. @@ -190,9 +190,9 @@ Currently supported parents: ### Default stages The [original implementation](https://gitlab.com/gitlab-org/gitlab/-/issues/847) of value stream analytics defined 7 stages. These stages are always available for each parent, however altering these stages is not possible. - + To make things efficient and reduce the number of records created, the default stages are expressed as in-memory objects (not persisted). When the user creates a custom stage for the first time, all the stages are persisted. This behavior is implemented in the value stream analytics service objects. - + The reason for this was that we'd like to add the abilities to hide and order stages later on. ## Data Collector diff --git a/doc/development/wikis.md b/doc/development/wikis.md index 7995afb1e17..f47c87137ae 100644 --- a/doc/development/wikis.md +++ b/doc/development/wikis.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w description: "GitLab's development guidelines for Wikis" --- -# Wikis development guide +# Wikis development guide **(FREE)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227027) in GitLab 13.5. |