Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-10-14 18:13:40 +00:00
parent 4898e4654b
commit 5ca32d2dac
18 changed files with 193 additions and 199 deletions

View File

@ -55,10 +55,12 @@ export default {
...mapActions(['fetchReports', 'setPaths']),
},
loadingText: sprintf(s__('ciReport|Loading %{reportName} report'), {
reportName: 'codeclimate',
// eslint-disable-next-line @gitlab/require-i18n-strings
reportName: 'Code quality',
}),
errorText: sprintf(s__('ciReport|Failed to load %{reportName} report'), {
reportName: 'codeclimate',
// eslint-disable-next-line @gitlab/require-i18n-strings
reportName: 'Code quality',
}),
};
</script>

View File

@ -1,5 +1,5 @@
import { spriteIcon } from '~/lib/utils/common_utils';
import { sprintf, __, s__, n__ } from '~/locale';
import { sprintf, s__ } from '~/locale';
import { LOADING, ERROR, SUCCESS, STATUS_NOT_FOUND } from '../../constants';
export const hasCodequalityIssues = (state) =>
@ -18,27 +18,23 @@ export const codequalityStatus = (state) => {
export const codequalityText = (state) => {
const { newIssues, resolvedIssues } = state;
const text = [];
let text;
if (!newIssues.length && !resolvedIssues.length) {
text.push(s__('ciReport|No changes to code quality'));
} else {
text.push(s__('ciReport|Code quality'));
if (resolvedIssues.length) {
text.push(n__(' improved on %d point', ' improved on %d points', resolvedIssues.length));
}
if (newIssues.length && resolvedIssues.length) {
text.push(__(' and'));
}
if (newIssues.length) {
text.push(n__(' degraded on %d point', ' degraded on %d points', newIssues.length));
}
text = s__('ciReport|No changes to code quality');
} else if (newIssues.length && resolvedIssues.length) {
text = sprintf(
s__(`ciReport|Code quality scanning detected %{issueCount} changes in merged results`),
{
issueCount: newIssues.length + resolvedIssues.length,
},
);
} else if (resolvedIssues.length) {
text = s__(`ciReport|Code quality improved`);
} else if (newIssues.length) {
text = s__(`ciReport|Code quality degraded`);
}
return text.join('');
return text;
};
export const codequalityPopover = (state) => {

View File

@ -1,5 +1,4 @@
<script>
/* eslint-disable @gitlab/require-string-literal-i18n-helpers */
import { GlButton, GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, n__, s__ } from '~/locale';
@ -41,7 +40,7 @@ export default {
return this.expanded ? 'chevron-down' : 'chevron-right';
},
commitsCountMessage() {
return n__(__('%d commit'), __('%d commits'), this.isSquashEnabled ? 1 : this.commitsCount);
return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
},
modifyLinkMessage() {
if (this.isFastForwardEnabled) return __('Modify commit message');

View File

@ -163,7 +163,6 @@ class GroupPolicy < BasePolicy
enable :admin_cluster
enable :read_deploy_token
enable :create_jira_connect_subscription
enable :update_runners_registration_token
enable :maintainer_access
end
@ -180,6 +179,7 @@ class GroupPolicy < BasePolicy
enable :update_default_branch_protection
enable :create_deploy_token
enable :destroy_deploy_token
enable :update_runners_registration_token
enable :owner_access
end

View File

@ -14,7 +14,7 @@ class PipelineProcessWorker
loggable_arguments 1
idempotent!
deduplicate :until_executing, feature_flag: :ci_idempotent_pipeline_process_worker
deduplicate :until_executing
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)

View File

@ -1,8 +0,0 @@
---
name: ci_idempotent_pipeline_process_worker
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62410
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332963
milestone: '14.0'
type: development
group: group::pipeline authoring
default_enabled: true

View File

@ -6,13 +6,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Implement Snowplow tracking
This guide describes how to implement and test Snowplow tracking using JavaScript and Ruby trackers.
This page describes how to:
- Implement Snowplow frontend and backend tracking
- Test Snowplow events
## Snowplow JavaScript frontend tracking
GitLab provides a `Tracking` interface that wraps the [Snowplow JavaScript tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/) to track custom events. For the recommended implementation type, see [Usage recommendations](#usage-recommendations).
GitLab provides a `Tracking` interface that wraps the [Snowplow JavaScript tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/)
to track custom events.
Tracking implementations must have an `action` and a `category`. You can provide additional [structured event taxonomy](index.md#structured-event-taxonomy) categories with an `extra` object that accepts key-value pairs.
For the recommended frontend tracking implementation, see [Usage recommendations](#usage-recommendations).
Tracking implementations must have an `action` and a `category`. You can provide additional
categories from the [structured event taxonomy](index.md#structured-event-taxonomy) with an `extra` object
that accepts key-value pairs.
| Field | Type | Default value | Description |
|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@ -50,17 +58,23 @@ The following example shows `data-track-*` attributes assigned to a button:
| Attribute | Required | Description |
|:----------------------|:---------|:------------|
| `data-track-action` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field is `activate_form_input` and clicking a button is `click_button`. Replaces `data-track-event`, which was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/290962) in GitLab 13.11. |
| `data-track-label` | false | The `label` as described in [structured event taxonomy](index.md#structured-event-taxonomy). |
| `data-track-property` | false | The `property` as described in [structured event taxonomy](index.md#structured-event-taxonomy). |
| `data-track-value` | false | The `value` as described in [structured event taxonomy](index.md#structured-event-taxonomy). If omitted, this is the element's `value` property or `undefined`. For checkboxes, the default value is the element's checked attribute or `0` when unchecked. |
| `data-track-extra` | false | A key-value pairs object passed as a valid JSON string. This is added to the `extra` property in our [`gitlab_standard`](schemas.md#gitlab_standard) schema. |
| `data-track-label` | false | The specific element or object to act on. This can be: the label of the element, for example, a tab labeled 'Create from template' for `create_from_template`; a unique identifier if no text is available, for example, `groups_dropdown_close` for closing the Groups dropdown in the top bar; or the name or title attribute of a record being created. |
| `data-track-property` | false | Any additional property of the element, or object being acted on. |
| `data-track-value` | false | Describes a numeric value or something directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. If omitted, this is the element's `value` property or `undefined`. For checkboxes, the default value is the element's checked attribute or `0` when unchecked. |
| `data-track-extra` | false | A key-value pair object passed as a valid JSON string. This attribute is added to the `extra` property in our [`gitlab_standard`](schemas.md#gitlab_standard) schema. |
| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](index.md#structured-event-taxonomy). |
#### Event listeners
Event listeners are bound at the document level to handle click events in elements with data attributes. This allows them to be handled on re-rendering and changes to the DOM. Because of the way these events are bound, click events should not stop from propagating up the DOM tree. If click events are stopped from propagating, you must implement listeners and follow the instructions in [Implement Vue component tracking](#implement-vue-component-tracking) or [Implement raw JavaScript tracking](#implement-raw-javascript-tracking).
Event listeners bind at the document level to handle click events in elements with data attributes.
This allows them to be handled when the DOM re-renders or changes. Document-level binding reduces
the likelihood that click events stop propagating up the DOM tree.
#### Available helpers
If click events stop propagating, you must implement listeners and [Vue component tracking](#implement-vue-component-tracking) or [raw JavaScript tracking](#implement-raw-javascript-tracking).
#### Helper methods
Use the following Ruby helper:
```ruby
tracking_attrs(label, action, property) # { data: { track_label... } }
@ -68,27 +82,32 @@ tracking_attrs(label, action, property) # { data: { track_label... } }
%button{ **tracking_attrs('main_navigation', 'click_button', 'navigation') }
```
#### Caveats
When using the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/helpers/tab_helper.rb#L76) be sure to wrap `html_options` under the `html_options` keyword argument.
Be careful, as this behavior can be confused with the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) that does not require additional wrapping of `html_options`
If you use the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/helpers/tab_helper.rb#L76), you must wrap `html_options` under the `html_options` keyword argument. If you
use the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to), you don't need to wrap `html_options`.
```ruby
# Bad
= nav_link(controller: ['dashboard/groups', 'explore/groups'], data: { track_label: "explore_groups", track_action: "click_button" })
= nav_link(controller: ['dashboard/groups', 'explore/groups'], data: { track_label: "explore_groups",
track_action: "click_button" })
# Good
= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "explore_groups", track_action: "click_button" } })
= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label:
"explore_groups", track_action: "click_button" } })
# Good (other helpers)
= link_to explore_groups_path, title: _("Explore"), data: { track_label: "explore_groups", track_action: "click_button" }
= link_to explore_groups_path, title: _("Explore"), data: { track_label: "explore_groups", track_action:
"click_button" }
```
### Implement Vue component tracking
For custom event tracking, use a Vue `mixin` in components. Vue `mixin` exposes the `Tracking.event` static method and the `track` method called from components or templates. You can specify tracking options in `data` or `computed`. These options override any defaults and allow the values to be dynamic from props or based on state.
For custom event tracking, use a Vue `mixin` in components. Vue `mixin` exposes the `Tracking.event`
static method and the `track` method called from components or templates. You can specify tracking
options in `data` or `computed`. These options override any defaults and allow the values to be dynamic
from props or based on state.
Default options are passed when an event is tracked from the component. If you don't specify an option, the default `document.body.dataset.page` is used. The default options are:
Default options are passed when an event is tracked from the component. If you don't specify an option,
the default `document.body.dataset.page` is used. The default options are:
- `category`
- `label`
@ -104,14 +123,15 @@ To implement Vue component tracking:
const trackingMixin = Tracking.mixin;
```
1. Provide categories to track the event from the component. For example, to track all events in a component with a label, use the `label` category:
1. Provide categories to track the event from the component. For example, to track all events in a
component with a label, use the `label` category:
```javascript
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin({ label: 'right_sidebar' });
```
1. In the component, declare the Vue `mixin`.
1. In the component, declare the Vue `mixin`:
```javascript
export default {
@ -173,7 +193,7 @@ To implement Vue component tracking:
</template>
```
#### Implementation example
The following example shows an implementation of Vue component tracking:
```javascript
export default {
@ -275,14 +295,14 @@ describe('MyTracking', () => {
### Form tracking
Enable Snowplow automatic [form tracking](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/javascript-tracker/javascript-tracker-v2/tracking-specific-events/#form-tracking) by calling `Tracking.enableFormTracking` (after the DOM is ready) and providing a `config` object that includes at least one of the following elements:
- `forms`: determines which forms are tracked, and are identified by the CSS class name.
- `fields`: determines which fields inside the tracked forms are tracked, and are identified by the field `name`.
An optional list of contexts can be provided as the second argument.
Note that our [`gitlab_standard`](schemas.md#gitlab_standard) schema is excluded from these events.
To enable Snowplow automatic [form tracking](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/javascript-tracker/javascript-tracker-v2/tracking-specific-events/#form-tracking):
1. Call `Tracking.enableFormTracking` when the DOM is ready.
1. Provide a `config` object that includes at least one of the following elements:
- `forms` determines the forms to track. Identified by the CSS class name.
- `fields` determines the fields inside the tracked forms to track. Identified by the field `name`.
1. Optional. Provide a list of contexts as the second argument. The [`gitlab_standard`](schemas.md#gitlab_standard) schema is excluded from these events.
```javascript
Tracking.enableFormTracking({
forms: { allow: ['sign-in-form', 'password-recovery-form'] },
@ -313,27 +333,15 @@ describe('MyFormTracking', () => {
});
```
## Implement Snowplow Ruby (Backend) tracking
## Implement Ruby backend tracking
GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/ruby-tracker/) for tracking custom events.
`Gitlab::Tracking` is an interface that wraps the [Snowplow Ruby Tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/ruby-tracker/) for tracking custom events.
Backend tracking provides:
Custom event tracking and instrumentation can be added by directly calling the `GitLab::Tracking.event` class method, which accepts the following arguments:
| argument | type | default value | description |
|------------|---------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `category` | String | | Area or aspect of the application. This could be `HealthCheckController` or `Lfs::FileTransformer` for instance. |
| `action` | String | | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. |
| `label` | String | nil | As described in [Structured event taxonomy](index.md#structured-event-taxonomy). |
| `property` | String | nil | As described in [Structured event taxonomy](index.md#structured-event-taxonomy). |
| `value` | Numeric | nil | As described in [Structured event taxonomy](index.md#structured-event-taxonomy). |
| `context` | Array\[SelfDescribingJSON\] | nil | An array of custom contexts to send with this event. Most events should not have any custom contexts. |
| `project` | Project | nil | The project associated with the event. |
| `user` | User | nil | The user associated with the event. |
| `namespace` | Namespace | nil | The namespace associated with the event. |
| `extra` | Hash | `{}` | Additional keyword arguments are collected into a hash and sent with the event. |
Tracking can be viewed as either tracking user behavior, or can be used for instrumentation to monitor and visualize performance over time in an area or aspect of code.
- User behavior tracking
- Instrumentation to monitor and visualize performance over time in a section or aspect of code.
To add custom event tracking and instrumentation, call the `GitLab::Tracking.event` class method.
For example:
```ruby
@ -347,10 +355,25 @@ class Projects::CreateService < BaseService
end
```
Use the following arguments:
| Argument | Type | Default value | Description |
|------------|---------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `category` | String | | Area or aspect of the application. For example, `HealthCheckController` or `Lfs::FileTransformer`. |
| `action` | String | | The action being taken. For example, a controller action such as `create`, or an Active Record callback. |
| `label` | String | nil | The specific element or object to act on. This can be one of the following: the label of the element, for example, a tab labeled 'Create from template' for `create_from_template`; a unique identifier if no text is available, for example, `groups_dropdown_close` for closing the Groups dropdown in the top bar; or the name or title attribute of a record being created. |
| `property` | String | nil | Any additional property of the element, or object being acted on. |
| `value` | Numeric | nil | Describes a numeric value or something directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. |
| `context` | Array\[SelfDescribingJSON\] | nil | An array of custom contexts to send with this event. Most events should not have any custom contexts. |
| `project` | Project | nil | The project associated with the event. |
| `user` | User | nil | The user associated with the event. |
| `namespace` | Namespace | nil | The namespace associated with the event. |
| `extra` | Hash | `{}` | Additional keyword arguments are collected into a hash and sent with the event. |
### Unit testing
Use the `expect_snowplow_event` helper when testing backend Snowplow events. See [testing best practices](
https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-snowplow-events) for details.
To test backend Snowplow events, use the `expect_snowplow_event` helper. For more information, see
[testing best practices](../testing_guide/best_practices.md#test-snowplow-events).
### Performance
@ -358,73 +381,72 @@ We use the [AsyncEmitter](https://docs.snowplowanalytics.com/docs/collecting-dat
## Develop and test Snowplow
There are several tools for developing and testing a Snowplow event.
To develop and test a Snowplow event, there are several tools to test frontend and backend events:
| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment |
|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------|
| Snowplow Analytics Debugger Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
| Snowplow Inspector Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** |
| Snowplow Micro | **{check-circle}** | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{dotted-circle}** |
| Snowplow Mini | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{status_preparing}** | **{status_preparing}** |
**Legend**
**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned
| Snowplow Analytics Debugger Chrome Extension | Yes | No | Yes | Yes | Yes |
| Snowplow Inspector Chrome Extension | Yes | No | Yes | Yes | Yes |
| Snowplow Micro | Yes | Yes | Yes | No | No |
### Test frontend events
To test frontend events in development:
Before you test frontend events in development, you must:
- [Enable Snowplow tracking in the Admin Area](index.md#enable-snowplow-tracking).
- Turn off any ad blockers that would prevent Snowplow JS from loading in your environment.
- Turn off "Do Not Track" (DNT) in your browser.
1. [Enable Snowplow tracking in the Admin Area](index.md#enable-snowplow-tracking).
1. Turn off ad blockers that could prevent Snowplow JavaScript from loading in your environment.
1. Turn off "Do Not Track" (DNT) in your browser.
All URLs are pseudonymized. The entity identifier [replaces](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/javascript-tracker/javascript-tracker-v2/tracker-setup/other-parameters-2/#Setting_a_custom_page_URL_and_referrer_URL) personally identifiable
information (PII). PII includes usernames, group, and project names.
#### Snowplow Analytics Debugger Chrome Extension
Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging, and local development environments.
[Snowplow Analytics Debugger](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html) is a browser extension for testing frontend events. It works in production, staging, and local development environments.
1. Install the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension.
1. Open Chrome DevTools to the Snowplow Analytics Debugger tab.
1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html).
#### Snowplow Inspector Chrome Extension
Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments.
Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works in production, staging, and local development environments.
1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en).
1. Open the Chrome extension by pressing the Snowplow Inspector icon beside the address bar.
1. Click around on a webpage with Snowplow and you should see JavaScript events firing in the inspector window.
1. To open the extension, select the Snowplow Inspector icon beside the address bar.
1. Click around on a webpage with Snowplow to see JavaScript events firing in the inspector window.
### Snowplow Micro
### Test backend events
Snowplow Micro is a very small version of a full Snowplow data collection pipeline: small enough that it can be launched by a test suite. Events can be recorded into Snowplow Micro just as they can a full Snowplow pipeline. Micro then exposes an API that can be queried.
#### Snowplow Micro
Snowplow Micro is a Docker-based solution for testing frontend and backend events in a local development environment. You must modify GDK using the instructions below to set this up.
[Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/) is a
Docker-based solution for testing backend and frontend in a local development environment. Snowplow Micro
records the same events as the full Snowplow pipeline. To query events, use the Snowplow Micro API.
- Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/)
- Look at the [Snowplow Micro repository](https://github.com/snowplow-incubator/snowplow-micro)
- Watch our <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag)
To install and run Snowplow Micro, complete these steps to modify the
[GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit):
1. Ensure Docker is installed and running.
1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro) by cloning the settings in [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration):
1. Navigate to the directory with the cloned project, and start the appropriate Docker
container with the following script:
1. To install Snowplow Micro, clone the settings in
[this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration).
1. Navigate to the directory with the cloned project,
and start the appropriate Docker container:
```shell
./snowplow-micro.sh
```
1. Use GDK to start the PostgreSQL terminal and connect to the `gitlabhq_development` database:
1. Use GDK to start the PostgreSQL terminal and connect
to the `gitlabhq_development` database:
```shell
gdk psql -d gitlabhq_development
```
1. Update your instance's settings to enable Snowplow events and point to the Snowplow Micro collector:
1. Update your instance's settings to enable Snowplow events and
point to the Snowplow Micro collector:
```shell
update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com';
@ -499,17 +521,16 @@ Snowplow Micro is a Docker-based solution for testing frontend and backend event
1. Navigate to `localhost:9090/micro/good` to see the event.
### Snowplow Mini
#### Useful links
[Snowplow Mini](https://github.com/snowplow/snowplow-mini) is an easily-deployable, single-instance version of Snowplow.
- [Snowplow Micro repository](https://github.com/snowplow-incubator/snowplow-micro)
- [Installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag)
Snowplow Mini can be used for testing frontend and backend events on a production, staging and local development environment.
### Troubleshoot
For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini.
### Troubleshooting
To control content security policy warnings when using an external host, you can allow or disallow them by modifying `config/gitlab.yml`. To allow them, add the relevant host for `connect_src`. For example, for `https://snowplow.trx.gitlab.net`:
To control content security policy warnings when using an external host, modify `config/gitlab.yml`
to allow or disallow them. To allow them, add the relevant host for `connect_src`. For example, for
`https://snowplow.trx.gitlab.net`:
```yaml
development:

View File

@ -4,40 +4,28 @@ 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
---
# Snowplow Guide
# Snowplow
This guide provides an overview of how Snowplow works.
For more information about Product Intelligence, see:
- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
- [Service Ping Guide](../service_ping/index.md)
More useful links:
- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
- [Data Analysis Process](https://about.gitlab.com/handbook/business-technology/data-team/#data-analysis-process/)
- [Data for Product Managers](https://about.gitlab.com/handbook/business-technology/data-team/programs/data-for-product-managers/)
- [Data Infrastructure](https://about.gitlab.com/handbook/business-technology/data-team/platform/infrastructure/)
This page provides an overview of how Snowplow works and how to enable it.
## What is Snowplow
Snowplow is an enterprise-grade marketing and Product Intelligence platform which helps track the way users engage with our website and application.
Snowplow is an enterprise-grade marketing and Product Intelligence platform that tracks how users engage with our website and application.
[Snowplow](https://snowplowanalytics.com) consists of several loosely-coupled sub-systems:
- **Trackers** fire Snowplow events. Snowplow has twelve trackers that cover web, mobile, desktop, server, and IoT.
- **Collectors** receive Snowplow events from trackers. We have three different event collectors that synchronize events to Amazon S3, Apache Kafka, or Amazon Kinesis.
- **Enrich** cleans up raw Snowplow events, enriches them, and puts them into storage. There is a Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process.
- **Storage** is where the Snowplow events live. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases.
- **Data modeling** is where event-level data joins other data sets and aggregates into smaller data sets, and business logic is applied. This produces a clean set of tables for data analysis. We have data models for Redshift and Looker.
- **Collectors** receive Snowplow events from trackers. We use different event collectors that synchronize events to Amazon S3, Apache Kafka, or Amazon Kinesis.
- **Enrich** cleans raw Snowplow events, enriches them, and puts them into storage. There is a Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process.
- **Storage** stores Snowplow events. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases.
- **Data modeling** joins event-level data with other data sets, aggregates them into smaller data sets, and applies business logic. This produces a clean set of tables for data analysis. We use data models for Redshift and Looker.
- **Analytics** are performed on Snowplow events or on aggregate tables.
![snowplow_flow](../img/snowplow_flow.png)
### Useful links
- [Understanding the structure of Snowplow data](https://docs.snowplowanalytics.com/docs/understanding-your-pipeline/canonical-event/)
- [Snowplow data structure](https://docs.snowplowanalytics.com/docs/understanding-your-pipeline/canonical-event/)
- [Our Iglu schema registry](https://gitlab.com/gitlab-org/iglu)
- [List of events used in our codebase (Event Dictionary)](https://metrics.gitlab.com/snowplow.html)
@ -46,7 +34,7 @@ Snowplow is an enterprise-grade marketing and Product Intelligence platform whic
Tracking can be enabled at:
- The instance level, which enables tracking on both the frontend and backend layers.
- The user level, though user tracking can be disabled on a per-user basis.
- The user level. User tracking can be disabled on a per user basis.
GitLab respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level.
Snowplow tracking is enabled on GitLab.com, and we use it for most of our tracking strategy.
@ -116,7 +104,7 @@ Each click event provides attributes that describe the event.
### Examples
| category* | label | action | property** | value |
| Category* | Label | Action | Property** | Value |
|-------------|------------------|-----------------------|----------|:-----:|
| `[root:index]` | `main_navigation` | `click_navigation_link` | `[link_label]` | - |
| `[groups:boards:show]` | `toggle_swimlanes` | `click_toggle_button` | - | `[is_active]` |
@ -126,8 +114,8 @@ Each click event provides attributes that describe the event.
| `[projects:clusters:new]` | `chart_options` | `generate_link` | `[chart_link]` | - |
| `[projects:clusters:new]` | `chart_options` | `click_add_label_button` | `[label_id]` | - |
_* It's ok to omit the category, and use the default._<br>
_** Property is usually the best place for variable strings._
_* If you choose to omit the category you can use the default._<br>
_** Use property for variable strings._
### Reference SQL
@ -173,4 +161,13 @@ LIMIT 100
### Web-specific parameters
Snowplow JS adds [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default.
Snowplow JavaScript adds [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default.
## Related topics
- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
- [Service Ping Guide](../service_ping/index.md)
- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
- [Data Analysis Process](https://about.gitlab.com/handbook/business-technology/data-team/#data-analysis-process/)
- [Data for Product Managers](https://about.gitlab.com/handbook/business-technology/data-team/programs/data-for-product-managers/)
- [Data Infrastructure](https://about.gitlab.com/handbook/business-technology/data-team/platform/infrastructure/)

View File

@ -28,7 +28,7 @@ events or touches Snowplow related files.
- For frontend events, when relevant, add a screenshot of the event in
the [testing tool](implementation.md#develop-and-test-snowplow) used.
- For backend events, when relevant, add the output of the
[Snowplow Micro](implementation.md#snowplow-mini) good events
[Snowplow Micro](implementation.md#snowplow-micro) good events
`GET http://localhost:9090/micro/good` (it might be a good idea
to reset with `GET http://localhost:9090/micro/reset` first).
- Update the [Event Dictionary](event_dictionary_guide.md).

View File

@ -24,14 +24,16 @@ If you find that you have to add the same badges to several projects, you may wa
To add a new badge to a project:
1. Navigate to your project's **Settings > General > Badges**.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > General**.
1. Expand **Badges**.
1. Under "Link", enter the URL that the badges should point to and under
"Badge image URL" the URL of the image that should be displayed.
1. Submit the badge by clicking the **Add badge** button.
1. Select **Add badge**.
After adding a badge to a project, you can see it in the list below the form.
You can edit it by clicking on the pen icon next to it or to delete it by
clicking on the trash icon.
You can edit the badge by selecting **Edit** (**{pencil}**) next to it or delete it by
selecting **Delete** (**{remove}**).
Badges associated with a group can only be edited or deleted on the
[group level](#group-badges).
@ -42,13 +44,15 @@ A common project badge presents the GitLab CI pipeline status.
To add this badge to a project:
1. Navigate to your project's **Settings > General > Badges**.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > General**.
1. Expand **Badges**.
1. Under **Name**, enter _Pipeline Status_.
1. Under **Link**, enter the following URL:
`https://gitlab.com/%{project_path}/-/commits/%{default_branch}`
1. Under **Badge image URL**, enter the following URL:
`https://gitlab.com/%{project_path}/badges/%{default_branch}/pipeline.svg`
1. Submit the badge by clicking the **Add badge** button.
1. Select **Add badge**.
## Group badges
@ -60,14 +64,16 @@ project, consider adding them on the [project level](#project-badges) or use
To add a new badge to a group:
1. Navigate to your group's **Settings > General > Badges**.
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Settings > General**.
1. Expand **Badges**.
1. Under "Link", enter the URL that the badges should point to and under
"Badge image URL" the URL of the image that should be displayed.
1. Submit the badge by clicking the **Add badge** button.
1. Select **Add badge**.
After adding a badge to a group, you can see it in the list below the form.
You can edit the badge by clicking on the pen icon next to it or to delete it
by clicking on the trash icon.
You can edit the badge by selecting **Edit** (**{pencil}**) next to it or delete it by
selecting **Delete** (**{remove}**).
Badges directly associated with a project can be configured on the
[project level](#project-badges).
@ -108,7 +114,8 @@ https://gitlab.example.com/<project_path>/-/raw/<default_branch>/my-image.svg
To add a new badge to a group or project with a custom image:
1. Go to your group or project and select **Settings > General**.
1. On the top bar, select **Menu** and find your group or project.
1. On the left sidebar, select **Settings > General**.
1. Expand **Badges**.
1. Under **Name**, enter the name for the badge.
1. Under **Link**, enter the URL that the badge should point to.

View File

@ -40,25 +40,12 @@ msgstr ""
msgid " You need to do this before %{grace_period_deadline}."
msgstr ""
msgid " and"
msgstr ""
msgid " and "
msgstr ""
msgid " and %{sliced}"
msgstr ""
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
msgstr[0] ""
msgstr[1] ""
msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
msgid " or "
msgstr ""
@ -197,9 +184,6 @@ msgid_plural "%d commits,"
msgstr[0] ""
msgstr[1] ""
msgid "%d commits"
msgstr ""
msgid "%d completed issue"
msgid_plural "%d completed issues"
msgstr[0] ""
@ -39986,7 +39970,13 @@ msgstr ""
msgid "ciReport|Cluster Image Scanning"
msgstr ""
msgid "ciReport|Code quality"
msgid "ciReport|Code quality degraded"
msgstr ""
msgid "ciReport|Code quality improved"
msgstr ""
msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
msgstr ""
msgid "ciReport|Container Scanning"

View File

@ -60,7 +60,7 @@ describe('Grouped code quality reports app', () => {
});
it('should render loading text', () => {
expect(findWidget().text()).toEqual('Loading codeclimate report');
expect(findWidget().text()).toEqual('Loading Code quality report');
});
});
@ -84,7 +84,7 @@ describe('Grouped code quality reports app', () => {
});
it('renders summary text', () => {
expect(findWidget().text()).toContain('Code quality degraded on 1 point');
expect(findWidget().text()).toContain('Code quality degraded');
});
it('renders custom codequality issue body', () => {
@ -99,7 +99,7 @@ describe('Grouped code quality reports app', () => {
});
it('renders summary text', () => {
expect(findWidget().text()).toContain('Code quality improved on 1 point');
expect(findWidget().text()).toContain('Code quality improved');
});
it('renders custom codequality issue body', () => {
@ -115,7 +115,7 @@ describe('Grouped code quality reports app', () => {
it('renders summary text', () => {
expect(findWidget().text()).toContain(
'Code quality improved on 1 point and degraded on 1 point',
'Code quality scanning detected 2 changes in merged results',
);
});
@ -132,7 +132,7 @@ describe('Grouped code quality reports app', () => {
});
it('renders error text', () => {
expect(findWidget().text()).toContain('Failed to load codeclimate report');
expect(findWidget().text()).toContain('Failed to load Code quality report');
});
it('does not render a help icon', () => {

View File

@ -61,9 +61,9 @@ describe('Codequality reports store getters', () => {
it.each`
resolvedIssues | newIssues | expectedText
${0} | ${0} | ${'No changes to code quality'}
${0} | ${1} | ${'Code quality degraded on 1 point'}
${2} | ${0} | ${'Code quality improved on 2 points'}
${1} | ${2} | ${'Code quality improved on 1 point and degraded on 2 points'}
${0} | ${1} | ${'Code quality degraded'}
${2} | ${0} | ${'Code quality improved'}
${1} | ${2} | ${'Code quality scanning detected 3 changes in merged results'}
`(
'returns a summary containing $resolvedIssues resolved issues and $newIssues new issues',
({ newIssues, resolvedIssues, expectedText }) => {

View File

@ -23,7 +23,7 @@ describe('Report section', () => {
const defaultProps = {
component: '',
status: 'SUCCESS',
loadingText: 'Loading codeclimate report',
loadingText: 'Loading Code Quality report',
errorText: 'foo',
successText: 'Code quality improved on 1 point and degraded on 1 point',
resolvedIssues,
@ -117,13 +117,13 @@ describe('Report section', () => {
vm = mountComponent(ReportSection, {
component: '',
status: 'LOADING',
loadingText: 'Loading codeclimate report',
loadingText: 'Loading Code Quality report',
errorText: 'foo',
successText: 'Code quality improved on 1 point and degraded on 1 point',
hasIssues: false,
});
expect(vm.$el.textContent.trim()).toEqual('Loading codeclimate report');
expect(vm.$el.textContent.trim()).toEqual('Loading Code Quality report');
});
});
@ -229,13 +229,13 @@ describe('Report section', () => {
vm = mountComponent(ReportSection, {
component: '',
status: 'ERROR',
loadingText: 'Loading codeclimate report',
errorText: 'Failed to load codeclimate report',
loadingText: 'Loading Code Quality report',
errorText: 'Failed to load Code Quality report',
successText: 'Code quality improved on 1 point and degraded on 1 point',
hasIssues: false,
});
expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report');
expect(vm.$el.textContent.trim()).toEqual('Failed to load Code Quality report');
});
});

View File

@ -1005,7 +1005,7 @@ RSpec.describe GroupPolicy do
context 'with maintainer' do
let(:current_user) { maintainer }
it { is_expected.to be_allowed(:update_runners_registration_token) }
it { is_expected.to be_disallowed(:update_runners_registration_token) }
end
context 'with reporter' do

View File

@ -118,7 +118,7 @@ RSpec.describe API::Ci::Runners do
end
include_context 'when authorized', 'group' do
let_it_be(:user) { create_default(:group_member, :maintainer, user: create(:user), group: group ).user }
let_it_be(:user) { create_default(:group_member, :owner, user: create(:user), group: group ).user }
def get_token
group.reload.runners_token

View File

@ -89,7 +89,7 @@ RSpec.describe 'RunnersRegistrationTokenReset' do
end
include_context 'when authorized', 'group' do
let_it_be(:user) { create_default(:group_member, :maintainer, user: create(:user), group: group ).user }
let_it_be(:user) { create_default(:group_member, :owner, user: create(:user), group: group ).user }
def get_token
group.reload.runners_token

View File

@ -29,16 +29,6 @@ RSpec.describe PipelineProcessWorker do
end
end
context 'when the FF ci_idempotent_pipeline_process_worker is disabled' do
before do
stub_feature_flags(ci_idempotent_pipeline_process_worker: false)
end
it 'is not deduplicated' do
expect(described_class).not_to be_deduplication_enabled
end
end
describe '#perform' do
context 'when pipeline exists' do
it 'processes pipeline' do