diff options
Diffstat (limited to 'doc/development/internal_analytics/internal_event_instrumentation')
6 files changed, 479 insertions, 0 deletions
diff --git a/doc/development/internal_analytics/internal_event_instrumentation/event_definition_guide.md b/doc/development/internal_analytics/internal_event_instrumentation/event_definition_guide.md new file mode 100644 index 00000000000..807e27d546e --- /dev/null +++ b/doc/development/internal_analytics/internal_event_instrumentation/event_definition_guide.md @@ -0,0 +1,60 @@ +--- +stage: Analyze +group: Analytics Instrumentation +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Event definition guide + +NOTE: +The event dictionary is a work in progress, and this process is subject to change. + +This guide describes the event dictionary and how it's implemented. + +## Event definition and validation + +This process is meant to document all internal events and ensure consistency. Every internal event needs to have such a definition. Event definitions must comply with the [JSON Schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/events/schema.json). + +All event definitions are stored in the following directories: + +- [`config/events`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/events) +- [`ee/config/events`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/config/events) + +Each event is defined in a separate YAML file consisting of the following fields: + +| Field | Required | Additional information | +|------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `description` | yes | A description of the event. | +| `category` | yes | Always InternalEventTracking (only different for legacy events). | +| `action` | yes | A unique name for the event. | +| `identifiers` | no | A list of identifiers sent with the event. Can be set to one or more of `project`, `user`, or `namespace`. | +| `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 event. | +| `product_group` | yes | The [group](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) that owns the event. | +| `milestone` | no | The milestone when the event is introduced. | +| `introduced_by_url` | no | The URL to the merge request that introduced the event. | +| `distributions` | yes | The [distributions](https://about.gitlab.com/handbook/marketing/brand-and-product-marketing/product-and-solution-marketing/tiers/#definitions) where the tracked feature is available. Can be set to one or more of `ce` or `ee`. | +| `tiers` | yes | The [tiers](https://about.gitlab.com/handbook/marketing/brand-and-product-marketing/product-and-solution-marketing/tiers/) where the tracked feature is available. Can be set to one or more of `free`, `premium`, or `ultimate`. | + +### Example event definition + +This is an example YAML file for an internal event: + +```yaml +description: A user visited a product analytics dashboard +category: InternalEventTracking +action: user_visited_dashboard +identifiers: +- project +- user +- namespace +product_section: dev +product_stage: analyze +product_group: group::product analytics +milestone: "16.4" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128029 +distributions: +- ee +tiers: +- ultimate +``` diff --git a/doc/development/internal_analytics/internal_event_instrumentation/index.md b/doc/development/internal_analytics/internal_event_instrumentation/index.md new file mode 100644 index 00000000000..35f9f31351e --- /dev/null +++ b/doc/development/internal_analytics/internal_event_instrumentation/index.md @@ -0,0 +1,16 @@ +--- +stage: Analyze +group: Analytics Instrumentation +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Internal Event Tracking + +This page provides detailed guidelines on using the Internal Event Tracking system to instrument features on GitLab. + +This page is a work in progress. If you have access to the GitLab Slack workspace, use the +`#g_analyze_analytics_instrumentation` channel for any questions or clarifications. + +- [Quick start for internal event tracking](quick_start.md#quick-start-for-internal-event-tracking) +- [Migrating existing tracking to internal event tracking](migration.md) +- [Event definition guide](event_definition_guide.md) diff --git a/doc/development/internal_analytics/internal_event_instrumentation/introduction.md b/doc/development/internal_analytics/internal_event_instrumentation/introduction.md new file mode 100644 index 00000000000..e776691fdf0 --- /dev/null +++ b/doc/development/internal_analytics/internal_event_instrumentation/introduction.md @@ -0,0 +1,13 @@ +--- +stage: Analyze +group: Analytics Instrumentation +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Internal event tracking + +This page is under construction. It serves as placeholder for the following information: + +- High level introduction +- Difference between Events and Metrics +- Basic overview of the architecture diff --git a/doc/development/internal_analytics/internal_event_instrumentation/local_setup_and_debugging.md b/doc/development/internal_analytics/internal_event_instrumentation/local_setup_and_debugging.md new file mode 100644 index 00000000000..d68e5565775 --- /dev/null +++ b/doc/development/internal_analytics/internal_event_instrumentation/local_setup_and_debugging.md @@ -0,0 +1,78 @@ +--- +stage: Analyze +group: Analytics Instrumentation +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Local setup and debugging + +Internal events are using a tool called Snowplow under the hood. To develop and test internal events, there are several tools related to Snowplow to test frontend and backend events: + +| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment | +|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------| +| Snowplow Analytics Debugger Chrome Extension | Yes | No | Yes | Yes | Yes | +| Snowplow Micro | Yes | Yes | Yes | No | No | + +For local development you will have to either [setup a local event collector](#setup-local-event-collector) or [configure a remote event collector](#configure-a-remote-event-collector). +We recommend the local setup when actively developing new events. + +## Setup local event collector + +By default, self-managed instances do not collect event data via Snowplow. We can use [Snowplow Micro](https://docs.snowplow.io/docs/testing-debugging/snowplow-micro/what-is-micro/), a Docker based Snowplow collector, to test events locally: + +1. Ensure [Docker is installed and working](https://www.docker.com/get-started). + +1. Enable Snowplow Micro: + + ```shell + gdk config set snowplow_micro.enabled true + ``` + +1. Optional. Snowplow Micro runs on port `9091` by default, you can change to `9092` by running: + + ```shell + gdk config set snowplow_micro.port 9092 + ``` + +1. Regenerate your Procfile and YAML config by reconfiguring GDK: + + ```shell + gdk reconfigure + ``` + +1. Restart the GDK: + + ```shell + gdk restart + ``` + +1. You can now see all events being sent by your local instance in the [Snowplow Micro UI](http://localhost:9091/micro/ui) and can filter for specific events. + +## Configure a remote event collector + +On GitLab.com events are sent to a collector configured by GitLab. By default, self-managed instances do not have a collector configured and do not collect data with Snowplow. + +You can configure your self-managed GitLab instance to use a custom Snowplow collector. + +1. On the left sidebar, select **Search or go to**. +1. Select **Admin Area**. +1. On the left sidebar, select **Settings > General**. +1. Expand **Snowplow**. +1. Select **Enable Snowplow tracking** and enter your Snowplow configuration information. For example: + + | Name | Value | + |--------------------|-------------------------------| + | Collector hostname | `your-snowplow-collector.net` | + | App ID | `gitlab` | + | Cookie domain | `.your-gitlab-instance.com` | + +1. Select **Save changes**. + +## Snowplow Analytics Debugger Chrome Extension + +[Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) is a browser extension for testing frontend events. +It works in production, staging, and local development environments. It is especially suited to verifying correct events are getting sent in a deployed environment. + +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 Debugger tab. +1. Any event triggered on a GitLab page should appear in the Snowplow Debugger tab. diff --git a/doc/development/internal_analytics/internal_event_instrumentation/migration.md b/doc/development/internal_analytics/internal_event_instrumentation/migration.md new file mode 100644 index 00000000000..2a3a3560292 --- /dev/null +++ b/doc/development/internal_analytics/internal_event_instrumentation/migration.md @@ -0,0 +1,162 @@ +--- +stage: Analyze +group: Analytics Instrumentation +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Migrating existing tracking to internal event tracking + +GitLab Internal Events Tracking exposes a unified API on top of the deprecated Snowplow and Redis/RedisHLL event tracking options. + +This page describes how you can switch from one of the previous methods to using Internal Events Tracking. + +NOTE: +Tracking events directly via Snowplow, Redis/RedisHLL is deprecated but won't be removed in the foreseeable future. +While we encourage you to migrate to Internal Event tracking the deprecated methods will continue to work for existing events and metrics. + +## Migrating from existing Snowplow tracking + +If you are already tracking events in Snowplow, you can also start collecting metrics from self-managed instances by switching to Internal Events Tracking. + +The event triggered by Internal Events has some special properties compared to previously tracking with Snowplow directly: + +1. The `label`, `property` and `value` attributes are not used within Internal Events and are always empty. +1. The `category` is automatically set to `InternalEventTracking` + +Please make sure that you are okay with this change before you migrate and dashboards are changed accordingly. + +### Backend + +If you are already tracking Snowplow events using `Gitlab::Tracking.event` and you want to migrate to Internal Events Tracking you might start with something like this: + +```ruby +Gitlab::Tracking.event(name, 'ci_templates_unique', namespace: namespace, + project: project, context: [context], user: user, label: label) +``` + +The code above can be replaced by this: + +```ruby +Gitlab::InternalEvents.track_event('ci_templates_unique', namespace: namespace, project: project, user: user) +``` + +In addition, you have to create definitions for the metrics that you would like to track. + +To generate metric definitions, you can use the generator like this: + +```shell +bin/rails g gitlab:analytics:internal_events \ + --time_frames=7d 28d\ + --group=project_management \ + --stage=plan \ + --section=dev \ + --event=ci_templates_unique \ + --unique=user.id \ + --mr=https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121544 +``` + +### Frontend + +If you are using the `Tracking` mixin in the Vue component, you can replace it with the `InternalEvents` mixin. + +For example, if your current Vue component look like this: + +```vue +import Tracking from '~/tracking'; +... +mixins: [Tracking.mixin()] +... +... +this.track('some_label', options) +``` + +After converting it to Internal Events Tracking, it should look like this: + +```vue +import { InternalEvents } from '~/tracking'; +... +mixins: [InternalEvents.mixin()] +... +... +this.trackEvent('action') +``` + +You can use [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123901/diffs) as an example. It migrates the `devops_adoption_app` component to use Internal Events Tracking. + +If you are using `data-track-action` in the component, you have to change it to `data-event-tracking` to migrate to Internal Events Tracking. + +For example, if a button is defined like this: + +```vue + <gl-button + :href="diffFile.external_url" + :title="externalUrlLabel" + :aria-label="externalUrlLabel" + target="_blank" + data-track-action="click_toggle_external_button" + data-track-label="diff_toggle_external_button" + data-track-property="diff_toggle_external" + icon="external-link" +/> +``` + +This can be converted to Internal Events Tracking like this: + +```vue + <gl-button + :href="diffFile.external_url" + :title="externalUrlLabel" + :aria-label="externalUrlLabel" + target="_blank" + data-event-tracking="click_toggle_external_button" + icon="external-link" +/> +``` + +Notice that we just need action to pass in the `data-event-tracking` attribute which will be passed to both Snowplow and RedisHLL. + +## Migrating from tracking with RedisHLL + +### Backend + +If you are currently tracking a metric in `RedisHLL` like this: + +```ruby + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:git_write_action, values: current_user.id) +``` + +To start using Internal Events Tracking, follow these steps: + +1. Create an event definition that describes `git_write_action` ([guide](event_definition_guide.md)). +1. Find metric definitions that list `git_write_action` in the events section (`20210216182041_action_monthly_active_users_git_write.yml` and `20210216184045_git_write_action_weekly.yml`). +1. Change the `data_source` from `redis_hll` to `internal_events` in the metric definition files. +1. Add an `events` section to both metric definition files. + + ```yaml + events: + - name: git_write_action + unique: user.id + ``` + + Use `project.id` or `namespace.id` instead of `user.id` if your metric is counting something other than unique users. +1. Call `InternalEvents.tract_event` instead of `HLLRedisCounter.track_event`: + + ```diff + - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:git_write_action, values: current_user.id) + + Gitlab::InternalEvents.track_event('project_created', user: current_user) + ``` + +1. Optional. Add additional values to the event. You typically want to add `project` and `namespace` as it is useful information to have in the data warehouse. + + ```diff + - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:git_write_action, values: current_user.id) + + Gitlab::InternalEvents.track_event('project_created', user: current_user, project: project, namespace: namespace) + ``` + +1. Update your test to use the `internal event tracking` shared example. + +### Frontend + +If you are calling `trackRedisHllUserEvent` in the frontend to track the frontend event, you can convert this to Internal events by using mixin, raw JavaScript or data tracking attribute, + +[Quick start guide](quick_start.md#frontend-tracking) has example for each methods. diff --git a/doc/development/internal_analytics/internal_event_instrumentation/quick_start.md b/doc/development/internal_analytics/internal_event_instrumentation/quick_start.md new file mode 100644 index 00000000000..271cb5f98a6 --- /dev/null +++ b/doc/development/internal_analytics/internal_event_instrumentation/quick_start.md @@ -0,0 +1,150 @@ +--- +stage: Analyze +group: Analytics Instrumentation +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Quick start for Internal Event Tracking + +In an effort to provide a more efficient, scalable, and unified tracking API, GitLab is deprecating existing RedisHLL and Snowplow tracking. Instead, we're implementing a new `track_event` (Backend) and `trackEvent`(Frontend) method. +With this approach, we can update both RedisHLL counters and send Snowplow events without worrying about the underlying implementation. + +In order to instrument your code with Internal Events Tracking you need to do three things: + +1. Define an event +1. Define one or more metrics +1. Trigger the event + +## Defining event and metrics + +<div class="video-fallback"> + See the video about <a href="https://www.youtube.com/watch?v=QICKWznLyy0">adding events and metrics using the generator</a> +</div> +<figure class="video_container"> + <iframe src="https://www.youtube-nocookie.com/embed/QICKWznLyy0" frameborder="0" allowfullscreen="true"> </iframe> +</figure> + +To create an event and metric definitions you can use the `internal_events` generator. + +This example creates an event definition for an event called `project_created` and two metric definitions, which are aggregated every 7 and 28 days. + +```shell +bundle exec rails generate gitlab:analytics:internal_events \ +--time_frames=7d 28d \ +--group=project_management \ +--stage=plan \ +--section=dev \ +--event=project_created \ +--unique=user.id \ +--mr=https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121544 +``` + +Where: + +- `time_frames`: Valid options are `7d` and `28d` if you provide a `unique` value and `all` for metrics without `unique`. We are working to make `7d` and `28d` work for metrics with `all` time frame in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/411264). +- `unique`: Valid options are `user.id`, `project.id`, and `namespace.id`, as they are logged as part of the standard context. We [are actively working](https://gitlab.com/gitlab-org/gitlab/-/issues/411255) on a way to define uniqueness on arbitrary properties sent with the event, such as `merge_request.id`. + +## Trigger events + +Triggering an event and thereby updating a metric is slightly different on backend and frontend. Please refer to the relevant section below. + +### Backend tracking + +To trigger an event, call the `Gitlab::InternalEvents.track_event` method with the desired arguments: + +```ruby +Gitlab::InternalEvents.track_event( + "i_code_review_user_apply_suggestion", + user: user, + namespace: namespace, + project: project + ) +``` + +This method automatically increments all RedisHLL metrics relating to the event `i_code_review_user_apply_suggestion`, and sends a corresponding Snowplow event with all named arguments and standard context (SaaS only). + +### Frontend tracking + +#### Vue components + +In Vue components, tracking can be done with [Vue mixin](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/tracking/internal_events.js#L29). + +To implement Vue component tracking: + +1. Import the `InternalEvents` library and call the `mixin` method: + + ```javascript + import { InternalEvents } from '~/tracking'; + const trackingMixin = InternalEvents.mixin(); + ``` + +1. Use the mixin in the component: + + ```javascript + export default { + mixins: [trackingMixin], + + data() { + return { + expanded: false, + }; + }, + }; + ``` + +1. Call the `trackEvent` method. Tracking options can be passed as the second parameter: + + ```javascript + this.trackEvent('i_code_review_user_apply_suggestion'); + ``` + + Or use the `trackEvent` method in the template: + + ```html + <template> + <div> + <button data-testid="toggle" @click="toggle">Toggle</button> + + <div v-if="expanded"> + <p>Hello world!</p> + <button @click="trackEvent('i_code_review_user_apply_suggestion')">Track another event</button> + </div> + </div> + </template> + ``` + +#### Raw JavaScript + +For tracking events directly from arbitrary frontend JavaScript code, a module for raw JavaScript is provided. This can be used outside of a component context where the Mixin cannot be utilized. + +```javascript +import { InternalEvents } from '~/tracking'; +InternalEvents.trackEvent('i_code_review_user_apply_suggestion'); +``` + +#### Data-track attribute + +This attribute ensures that if we want to track GitLab internal events for a button, we do not need to write JavaScript code on Click handler. Instead, we can just add a data-event-tracking attribute with event value and it should work. This can also be used with HAML views. + +```html + <gl-button + data-event-tracking="i_analytics_dev_ops_adoption" + > + Click Me + </gl-button> +``` + +#### Haml + +```haml += render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle', data: { event_tracking: 'action' }}) do +``` + +#### Internal events on render + +Sometimes we want to send internal events when the component is rendered or loaded. In these cases, we can add the `data-event-tracking-load="true"` attribute: + +```haml += render Pajamas::ButtonComponent.new(button_options: { data: { event_tracking_load: 'true', event_tracking: 'i_devops' } }) do + = _("New project") +``` |