2020-10-30 21:08:52 +00:00
---
2020-11-17 15:09:28 +00:00
stage: Enablement
group: Infrastructure
2020-11-26 06:09:20 +00:00
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
2020-10-30 21:08:52 +00:00
---
2020-07-10 12:09:15 +00:00
# Feature Categorization
> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/269) in GitLab 13.2.
2020-11-17 18:09:20 +00:00
Each Sidekiq worker, controller action, or API endpoint
2020-07-10 12:09:15 +00:00
must declare a `feature_category` attribute. This attribute maps each
of these to a [feature
2020-12-07 21:10:08 +00:00
category](https://about.gitlab.com/handbook/product/categories/). This
2020-07-10 12:09:15 +00:00
is done for error budgeting, alert routing, and team attribution.
The list of feature categories can be found in the file `config/feature_categories.yml` .
This file is generated from the
[`stages.yml` ](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml )
data file used in the GitLab Handbook and other GitLab resources.
## Updating `config/feature_categories.yml`
Occasionally new features will be added to GitLab stages, groups, and
product categories. When this occurs, you can automatically update
`config/feature_categories.yml` by running
`scripts/update-feature-categories` . This script will fetch and parse
[`stages.yml` ](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml )
and generate a new version of the file, which needs to be committed to
the repository.
2020-10-07 00:08:24 +00:00
The [Scalability
2020-08-06 15:09:42 +00:00
team](https://about.gitlab.com/handbook/engineering/infrastructure/team/scalability/)
2020-10-07 21:08:21 +00:00
currently maintains the `feature_categories.yml` file. They will automatically be
2020-07-10 12:09:15 +00:00
notified on Slack when the file becomes outdated.
## Sidekiq workers
The declaration uses the `feature_category` class method, as shown below.
```ruby
class SomeScheduledTaskWorker
include ApplicationWorker
# Declares that this worker is part of the
# `continuous_integration` feature category
feature_category :continuous_integration
# ...
end
```
The feature categories specified using `feature_category` should be
defined in
[`config/feature_categories.yml` ](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/feature_categories.yml ). If
not, the specs will fail.
### Excluding Sidekiq workers from feature categorization
A few Sidekiq workers, that are used across all features, cannot be mapped to a
2022-04-05 12:10:23 +00:00
single category. These should be declared as such using the
`feature_category :not_owned`
2020-07-10 12:09:15 +00:00
declaration, as shown below:
```ruby
class SomeCrossCuttingConcernWorker
include ApplicationWorker
# Declares that this worker does not map to a feature category
2022-04-05 12:10:23 +00:00
feature_category :not_owned # rubocop:disable Gitlab/AvoidFeatureCategoryNotOwned
2020-07-10 12:09:15 +00:00
# ...
end
```
2021-09-21 18:11:18 +00:00
When possible, workers marked as "not owned" use their caller's
category (worker or HTTP endpoint) in metrics and logs.
2021-09-21 00:09:28 +00:00
For instance, `ReactiveCachingWorker` can have multiple feature
categories in metrics and logs.
2020-07-10 12:09:15 +00:00
## Rails controllers
Specifying feature categories on controller actions can be done using
the `feature_category` class method.
A feature category can be specified on an entire controller
using:
```ruby
2020-10-02 12:09:03 +00:00
class Boards::ListsController < ApplicationController
feature_category :kanban_boards
2020-07-10 12:09:15 +00:00
end
```
The feature category can be limited to a list of actions using the
2020-10-02 12:09:03 +00:00
second argument:
2020-07-10 12:09:15 +00:00
```ruby
2020-10-02 12:09:03 +00:00
class DashboardController < ApplicationController
2021-10-27 15:13:41 +00:00
feature_category :team_planning, [:issues, :issues_calendar]
2020-10-02 12:09:03 +00:00
feature_category :code_review, [:merge_requests]
2020-07-10 12:09:15 +00:00
end
```
2020-10-02 12:09:03 +00:00
These forms cannot be mixed: if a controller has more than one category,
every single action must be listed.
2020-07-10 12:09:15 +00:00
### Excluding controller actions from feature categorization
In the rare case an action cannot be tied to a feature category this
can be done using the `not_owned` feature category.
```ruby
class Admin::LogsController < ApplicationController
feature_category :not_owned
end
```
### Ensuring feature categories are valid
The `spec/controllers/every_controller_spec.rb` will iterate over all
defined routes, and check the controller to see if a category is
assigned to all actions.
2020-10-02 12:09:03 +00:00
The spec also validates if the used feature categories are known. And if
the actions used in configuration still exist as routes.
2020-11-17 18:09:20 +00:00
## API endpoints
2020-12-10 15:10:12 +00:00
The [GraphQL API ](../../api/graphql/index.md ) is currently categorized
2021-01-12 00:10:42 +00:00
as `not_owned` . For now, no extra specification is needed. For more
2020-12-10 15:10:12 +00:00
information, see
[`gitlab-com/gl-infra/scalability#583` ](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/583/ ).
2020-11-17 18:09:20 +00:00
Grape API endpoints can use the `feature_category` class method, like
[Rails controllers ](#rails-controllers ) do:
```ruby
module API
class Issues < ::API::Base
2021-10-27 15:13:41 +00:00
feature_category :team_planning
2020-11-17 18:09:20 +00:00
end
end
```
The second argument can be used to specify feature categories for
specific routes:
```ruby
module API
class Users < ::API::Base
feature_category :users, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key']
end
end
```
Or the feature category can be specified in the action itself:
```ruby
module API
class Users < ::API::Base
get ':id', feature_category: :users do
end
end
end
```
As with Rails controllers, an API class must specify the category for
every single action unless the same category is used for every action
within that class.