diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-24 21:11:45 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-24 21:11:45 +0300 |
commit | 4bb797f25563205cf495f4dd5366e037e88831ab (patch) | |
tree | a345ddbd0e2464067323d3c6fd34960607ef4f44 /doc/development | |
parent | 40a4f37126bb1a1dd6b6f4b3c0ebb414a3e3908a (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'doc/development')
-rw-r--r-- | doc/development/fe_guide/style/typescript.md | 109 | ||||
-rw-r--r-- | doc/development/internal_analytics/internal_event_instrumentation/local_setup_and_debugging.md | 53 |
2 files changed, 141 insertions, 21 deletions
diff --git a/doc/development/fe_guide/style/typescript.md b/doc/development/fe_guide/style/typescript.md index 9497a0742e7..529459097b4 100644 --- a/doc/development/fe_guide/style/typescript.md +++ b/doc/development/fe_guide/style/typescript.md @@ -1,6 +1,7 @@ --- -stage: Create -group: Editor Extensions +type: reference, dev +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/product/ux/technical-writing/#assignments --- @@ -28,27 +29,79 @@ The following GitLab projects use TypeScript: - [`gitlab-language-server-for-code-suggestions`](https://gitlab.com/gitlab-org/editor-extensions/gitlab-language-server-for-code-suggestions) - [`gitlab-org/cluster-integration/javascript-client`](https://gitlab.com/gitlab-org/cluster-integration/javascript-client) -## Recommended configurations +## Recommendations -The [GitLab Workflow Extension](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main) project is a good model -for a project's TypeScript configuration. Consider copying the `.tsconfig` and `.eslintrc.json` from there. +### Setup ESLint and TypeScript configuration -- In `.tsconfig`, make sure [`"strict": true`](https://www.typescriptlang.org/tsconfig#strict) is set. -- In `.eslintrc.json`, make sure that TypeScript-specific parsing and linting is placed in an `overrides` for `**/*.ts` files. +When setting up a new TypeScript project, configure strict type-safety rules for +ESLint and TypeScript. This ensures that the project remains as type-safe as possible. -## Future plans +The [GitLab Workflow Extension](https://gitlab.com/gitlab-org/gitlab-vscode-extension/) +project is a good model for a TypeScript project's boilerplate and configuration. +Consider copying the `tsconfig.json` and `.eslintrc.json` from there. -- Shared ESLint configuration to reuse across TypeScript projects. +For `tsconfig.json`: + +- Use [`"strict": true`](https://www.typescriptlang.org/tsconfig#strict). + This enforces the strongest type-checking capabilities in the project and + prohibits overriding type-safety. +- Use [`"skipLibCheck": true`](https://www.typescriptlang.org/tsconfig#skipLibCheck). + This improves compile time by only checking references `.d.ts` + files as opposed to all `.d.ts` files in `node_modules`. + +For `.eslintrc.json` (or `.eslintrc.js`): + +- Make sure that TypeScript-specific parsing and linting are placed in an `overrides` + for `**/*.ts` files. This way, linting regular `.js` files + remains unaffected by the TypeScript-specific rules. +- Extend from [`plugin:@typescript-eslint/recommended`](https://typescript-eslint.io/rules?supported-rules=recommended) + which has some very sensible defaults, such as: + - [`"@typescript-eslint/no-explicit-any": "error"`](https://typescript-eslint.io/rules/no-explicit-any/) + - [`"@typescript-eslint/no-unsafe-assignment": "error"`](https://typescript-eslint.io/rules/no-unsafe-assignment/) + - [`"@typescript-eslint/no-unsafe-return": "error"`](https://typescript-eslint.io/rules/no-unsafe-return) + +### Avoid `any` + +Avoid `any` at all costs. This should already be configured in the project's linter, +but it's worth calling out here. + +Developers commonly resort to `any` when dealing with data structures that cross +domain boundaries, such as handling HTTP responses or interacting with untyped +libraries. This appears convenient at first. However, opting for a well-defined type (or using +`unknown` and employing type narrowing through predicates) carries substantial benefits. + +```typescript +// Bad :( +function handleMessage(data: any) { + console.log("We don't know what data is. This could blow up!", data.special.stuff); +} + +// Good :) +function handleMessage(data: unknown) { + console.log("Sometimes it's okay that it remains unknown.", JSON.stringify(data)); +} + +// Also good :) +function isFooMessage(data: unknown): data is { foo: string } { + return typeof data === 'object' && data && 'foo' in data; +} -## Recommended patterns +function handleMessage(data: unknown) { + if (isFooMessage(data)) { + console.log("We know it's a foo now. This is safe!", data.foo); + } +} +``` ### Avoid casting with `<>` or `as` -Avoid casting with `<>` or `as` as much as possible. This circumvents Type safety. Consider using +Avoid casting with `<>` or `as` as much as possible. + +Type casting explicitly circumvents type-safety. Consider using [type predicates](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates). ```typescript -// Bad +// Bad :( function handler(data: unknown) { console.log((data as StuffContainer).stuff); } @@ -72,22 +125,34 @@ function handler(data: unknown) { ``` -### Prefer `interface` over `type` for new interfaces +There's some rare cases this might be acceptable (consider +[this test utility](https://gitlab.com/gitlab-org/gitlab-web-ide/-/blob/3ea8191ed066811caa4fb108713e7538b8d8def1/packages/vscode-extension-web-ide/test-utils/createFakePartial.ts#L1)). However, 99% of the +time, there's a better way. + +### Prefer `interface` over `type` for new structures -Prefer interface over type declaration when describing structures. +Prefer declaring a new `interface` over declaring a new `type` alias when defining new structures. + +Interfaces and type aliases have a lot of cross-over, but only interfaces can be used +with the `implements` keyword. A class is not able to `implement` a `type` (only an `interface`), +so using `type` would restrict the usability of the structure. ```typescript -// Bad +// Bad :( type Fooer = { foo: () => string; } -// Good +// Good :) interface Fooer { foo: () => string; } ``` +From the [TypeScript guide](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces): + +> If you would like a heuristic, use `interface` until you need to use features from `type`. + ### Use `type` to define aliases for existing types Use type to define aliases for existing types, classes or interfaces. Use @@ -101,21 +166,21 @@ interface Config = { isBad: boolean; } -// Bad +// Bad :( type PartialConfig = { foo?: string; isBad?: boolean; } -// Good +// Good :) type PartialConfig = Partial<Config>; ``` ### Use union types to improve inference ```typescript -// Bad +// Bad :( interface Foo { type: string } interface FooBar extends Foo { bar: string } interface FooZed extends Foo { zed: string } @@ -128,7 +193,7 @@ const doThing = (foo: Foo) => { } // Good :) -interface FooBar { type: 'bar', bar: string }; +interface FooBar { type: 'bar', bar: string } interface FooZed { type: 'zed', zed: string } type Foo = FooBar | FooZed; @@ -140,6 +205,10 @@ const doThing = (foo: Foo) => { } ``` +## Future plans + +- Shared ESLint configuration to reuse across TypeScript projects. + ## Related topics - [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html) 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 index d68e5565775..d9f45a2d93e 100644 --- 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 @@ -14,7 +14,7 @@ Internal events are using a tool called Snowplow under the hood. To develop and | 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. +We recommend using the local setup together with the [internal events monitor](#internal-events-monitor) when actively developing new events. ## Setup local event collector @@ -68,6 +68,57 @@ You can configure your self-managed GitLab instance to use a custom Snowplow col 1. Select **Save changes**. +## Internal Events Monitor + +<div class="video-fallback"> + Watch the demo video about the <a href="https://www.youtube.com/watch?v=R7vT-VEzZOI">Internal Events Tracking Monitor</a> +</div> +<figure class="video_container"> + <iframe src="https://www.youtube-nocookie.com/embed/R7vT-VEzZOI" frameborder="0" allowfullscreen="true"> </iframe> +</figure> + +To understand how events are triggered and metrics are updated while you use the Rails app locally or `rails console`, +you can use the monitor. + +Start the monitor and list one or more events that you would like to monitor. In this example we would like to monitor `i_code_review_user_create_mr`. + +```shell +rails runner scripts/internal_events/monitor.rb i_code_review_user_create_mr +``` + +The monitor shows two tables. The top table lists all the metrics that are defined on the `i_code_review_user_create_mr` event. +The second right-most column shows the value of each metric when the monitor was started and the right most column shows the current value of each metric. +The bottom table has a list selected properties of all Snowplow events that matches the event name. + +If a new `i_code_review_user_create_mr` event is fired, the metrics values will get updated and a new event will appear in the `SNOWPLOW EVENTS` table. + +The monitor looks like below. + +```plaintext +Updated at 2023-10-11 10:17:59 UTC +Monitored events: i_code_review_user_create_mr + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| RELEVANT METRICS | ++-----------------------------------------------------------------------------+------------------------------+-----------------------+---------------+---------------+ +| Key Path | Monitored Events | Instrumentation Class | Initial Value | Current Value | ++-----------------------------------------------------------------------------+------------------------------+-----------------------+---------------+---------------+ +| counts_monthly.aggregated_metrics.code_review_category_monthly_active_users | i_code_review_user_create_mr | AggregatedMetric | 13 | 14 | +| counts_monthly.aggregated_metrics.code_review_group_monthly_active_users | i_code_review_user_create_mr | AggregatedMetric | 13 | 14 | +| counts_weekly.aggregated_metrics.code_review_category_monthly_active_users | i_code_review_user_create_mr | AggregatedMetric | 0 | 1 | +| counts_weekly.aggregated_metrics.code_review_group_monthly_active_users | i_code_review_user_create_mr | AggregatedMetric | 0 | 1 | +| redis_hll_counters.code_review.i_code_review_user_create_mr_monthly | i_code_review_user_create_mr | RedisHLLMetric | 8 | 9 | +| redis_hll_counters.code_review.i_code_review_user_create_mr_weekly | i_code_review_user_create_mr | RedisHLLMetric | 0 | 1 | ++-----------------------------------------------------------------------------+------------------------------+-----------------------+---------------+---------------+ ++---------------------------------------------------------------------------------------------------------+ +| SNOWPLOW EVENTS | ++------------------------------+--------------------------+---------+--------------+------------+---------+ +| Event Name | Collector Timestamp | user_id | namespace_id | project_id | plan | ++------------------------------+--------------------------+---------+--------------+------------+---------+ +| i_code_review_user_create_mr | 2023-10-11T10:17:15.504Z | 29 | 93 | | default | ++------------------------------+--------------------------+---------+--------------+------------+---------+ +``` + ## 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. |