scripts/internal_events/cli/text/event_definer.rb (100 lines of code) (raw):
# frozen_string_literal: true
module InternalEventsCli
module Text
module EventDefiner
extend Helpers
DESCRIPTION_INTRO = <<~TEXT.freeze
#{format_info('EVENT DESCRIPTION')}
Include what the event is supposed to track, where, and when.
The description field helps others find & reuse this event. This will be used by Engineering, Product, Data team, Support -- and also GitLab customers directly. Be specific and explicit.
ex - Debian package published to the registry using a deploy token
ex - Issue confidentiality was changed
TEXT
DESCRIPTION_HELP = <<~TEXT.freeze
#{format_warning('Required. 10+ words likely, but length may vary.')}
#{format_info('GOOD EXAMPLES:')}
- Pipeline is created with a CI Template file included in its configuration
- Quick action `/assign @user1` used to assign a single individual to an issuable
- Quick action `/target_branch` used on a Merge Request
- Quick actions `/unlabel` or `/remove_label` used to remove one or more specific labels
- User edits file using the single file editor
- User edits file using the Web IDE
- User removed issue link between issue and incident
- Debian package published to the registry using a deploy token
#{format_info('GUT CHECK:')}
For your description...
1. Would two different engineers likely instrument the event from the same code locations?
2. Would a new GitLab user find where the event is triggered in the product?
3. Would a GitLab customer understand what the description says?
TEXT
ACTION_INTRO = <<~TEXT.freeze
#{format_info('EVENT NAME')}
The event name is a unique identifier used from both a) app code and b) metric definitions.
The name should concisely communicate the same information as the event description.
ex - change_time_estimate_on_issue
ex - push_package_to_repository
ex - publish_go_module_to_the_registry_from_pipeline
ex - admin_user_comments_on_issue_while_impersonating_blocked_user
#{format_info('EXPECTED FORMAT:')} #{format_selection('<action>_<target_of_action>_<where/when>')}
ex) click_save_button_in_issue_description_within_15s_of_page_load
- ACTION: click
- TARGET: save button
- WHERE: in issue description
- WHEN: within 15s of page load
TEXT
ACTION_HELP = <<~TEXT.freeze
#{format_warning('Required. Must be globally unique. Must use only letters/numbers/underscores.')}
#{format_info('FAQs:')}
- Q: Present tense or past tense?
A: Prefer present tense! But it's up to you.
- Q: Other event names have prefixes like `i_` or the `g_group_name`. Why?
A: Those are leftovers from legacy naming schemes. Changing the names of old events/metrics can break dashboards, so stability is better than uniformity.
TEXT
IDENTIFIERS_INTRO = <<~TEXT.freeze
#{format_info('KEY IDENTIFIERS')}
Indicates the attributes recorded when the event occurs. Generally, we want to include every identifier available to us when the event is triggered.
#{format_info('BACKEND')}: Attributes must be specified when the event is triggered
ex) User, project, and namespace are the identifiers available for backend instrumentation:
track_internal_event(
'%s',
user: user,
project: project,
namespace: project.namespace
)
#{format_info('FRONTEND')}: Attributes are automatically included from the URL
ex) When a user takes an action on the MR list page, the URL is https://gitlab.com/gitlab-org/gitlab/-/merge_requests
Because this URL is for a project, we know that all of user/project/namespace are available for the event
#{format_info('NOTE')}: If you're planning to instrument a unique-by-user metric, you should still include project & namespace when possible. This is especially helpful in the data warehouse, where namespace and project can make events relevant for CSM use-cases.
TEXT
IDENTIFIER_OPTIONS = {
%w[project namespace user] =>
'Use case: For project-level user actions (ex - issue_assignee_changed) [MOST COMMON]',
%w[namespace user] =>
'Use case: For namespace-level user actions (ex - epic_assigned_to_milestone)',
%w[user] =>
'Use case: For user-only actions (ex - admin_impersonated_user)',
%w[project namespace] =>
'Use case: For project-level events without user interaction (ex - service_desk_request_received)',
%w[namespace] =>
'Use case: For namespace-level events without user interaction (ex - stale_runners_cleaned_up)',
%w[feature_enabled_by_namespace_ids user] =>
'Use case: For user actions attributable to multiple namespaces (ex - Code-Suggestions / Duo Pro)',
%w[] =>
'Use case: For instance-level events without user interaction [LEAST COMMON]'
}.freeze
ADDITIONAL_PROPERTIES_INTRO = <<~TEXT.freeze
#{format_info('ADDITIONAL PROPERTIES')}
Describe any related attributes or information which should be tracked when the event occurs. This enables extra capabilities:
- Service Ping: define metrics filtered to a specific subset of events (built-in properties only)
- Snowflake: view/sort/group individual events from GitLab.com
BUILT-IN PROPERTIES (recommended)
For the best performance and flexibility, provide event context using:
property (string), label (string), value (numeric)
These attribute names correspond to repurposed fields in Snowflake. They have no special meaning other than data type.
ex) To add a metric like "Monthly count of unique users who changed an MR status to closed" using a 'change_merge_request_status' event, define an additional property like:
Attribute: label (string)
Description: Status of merge request after update (one of opened, merged, closed)
CUSTOM PROPERTIES (as-needed)
When the built-in properties are insufficient, properties of any name can be provided.
This option becomes available after both property and label are defined, or after value is defined.
WARNING: Make sure the additional properties don’t contain any sensitive information, like customer data or PII.
For more information, see the Data Classification Standard at https://about.gitlab.com/handbook/security/data-classification-standard/
TEXT
ADDITIONAL_PROPERTIES_ADD_MORE_HELP = <<~TEXT.freeze
#{format_warning('Required. Must be unique within the event context. Must use only letters/numbers/underscores.')}
#{format_info('It should not be named any of the following:')}
- property#{' '}
- label
- value
TEXT
end
end
end