Skip to content

Commit

Permalink
Sync dev docs (#11105)
Browse files Browse the repository at this point in the history
  • Loading branch information
a-hariti committed Aug 15, 2024
1 parent 4427b8c commit 203f2ad
Show file tree
Hide file tree
Showing 12 changed files with 535 additions and 77 deletions.
38 changes: 29 additions & 9 deletions develop-docs/application/feature-flags/flagpole.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
---
title: Flagpole
---
# Flagpole

Flagpole is Sentry's internal, options-backed feature flagging library.

Expand Down Expand Up @@ -43,6 +41,7 @@ options:
: A wrapper around a list of conditions, acting as a logical grouping of customers/entities to enable the feature flag for. Segments allow you to create `OR` operations with other segments, meaning at least one segment must evaluate to `True` for a feature to be granted. If an empty segments list is provided, the feature will evaluate to `False`.

### Segments

`conditions`

: A list of predicates to evaluate for the feature flag to be enabled for this segment. All conditions in a segment must be evaluate to `True` in order for the segment to be enabled. If no conditions are defined, the segment will evaluate to `False`.
Expand Down Expand Up @@ -98,9 +97,11 @@ Flagpole currently supports the following `operator` types:
: The inverse of `equals`, evaluates to `True` if the context property value does not match the provided value.

## Evaluation Contexts

When a feature flag is checked, the caller must provide one or more entity objects for the feature handler to match against. These objects are used to construct an `EvaluationContext`, which is essentially a flat dictionary of keys and primitive values. This context is passed to each feature, which provides this context to each segment and condition to enforce whether the feature should be enabled.

### Context Builders

Each evaluation context is built up in stages via a [`ContextBuilder`](https://github.com/getsentry/sentry/blob/3cbf73a389a4ea006cbad9d8c4b8073effe09393/src/flagpole/evaluation_context.py#L54) object.

Each context builder consists of a list of context transformers, which are responsible for creating individual slices of the larger evaluation context.
Expand All @@ -113,6 +114,10 @@ Here are some common properties we surface via our Sentry and GetSentry context

: The sentry region or single-tenant the flag check is being perfomed in.

`sentry_singletenant` [bool]

: Whether or not the application is operating in a single-tenant environment.

**Organization Context Properties**

`organization_id` [int]
Expand Down Expand Up @@ -176,22 +181,37 @@ features.add(
feature.<feature_scope>:<feature_name>
```

<Alert level="info">
The feature config should not be merged until the registration commit in step 1 has been fully deployed to all target environments. This is because Options Automator will fail to push options to any environments missing the option registration.
If this happens, make sure to rerun the options deployment once all environments have been updated to ensure your feature is active.
</Alert>

Once the option change is deployed, the feature checks will immediately be active in all environments and regions.

_Note:_ The feature config should not be merged until the registration commit in step 1 has been fully deployed to all target environments. This is because Options Automator will fail to push options to any environments missing the option registration.
## Using Flagpole in single-tenants

If this happens, make sure to rerun the options deployment once all environments have been updated to ensure your feature is active.
To allow your flagpole feature configuration to be used in single-tenant
environments, you'll need to add your feature name to the
`flagpole.allowed_features` list for each tenant. For example, in
`options/regions/acme.yml` add the following:

```yaml
options:
flagpole.allowed_features: ["organizations:is_sentry"]
```

You can also use the `sentry_singletenant` and `sentry_region` context values in
your feature conditions as required.

## Testing a Flagpole feature locally

You can test a flagpole feature flag locally using the GetSentry devserver.
Because the feature handler for Flagpole only exists in GetSentry, it's not possible
to test flagpole features using the Sentry devserver at this time.

Start by creating a new yaml file containing your feature config. The config
file should contain a top-level `options` object containing your feature object,
and a `flagpole.flagpole_only_features` list option containing the name of the
feature you want to test, without the `feature.` prefix:
Start by creating a new yaml file containing your feature config:
```yaml
options:
'feature.organizations:is_sentry':
created_at: '2024-06-01T00:00:00.000000'
enabled: false
Expand Down
29 changes: 17 additions & 12 deletions develop-docs/application/feature-flags/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ They're declared on the `FeatureManager` like so:
```python
# pass FeatureHandlerStrategy.FLAGPOLE to use our options-backed feature flagging system:
manager.add("organizations:onboarding", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE)

# pass FeatureHandlerStrategy.INTERNAL if you don't plan to use options automator:
manager.add("organizations:onboarding", OrganizationFeature, FeatureHandlerStrategy.INTERNAL)

# [DEPRECATED] pass FeatureHandlerStrategy.OPTIONS to use options automator:
manager.add("organizations:onboarding", OrganizationFeature, FeatureHandlerStrategy.OPTIONS)
```
Expand Down Expand Up @@ -57,22 +59,27 @@ Most Sentry feature flags are placed in `temporary.py`, while permanent Sentry f

GetSentry only flags are typically placed in [`features.py`](https://github.com/getsentry/getsentry/blob/master/getsentry/features.py).

### Determine whether your feature needs to be exposed in the API

If you plan on using your feature in the frontend, you need to set
`api_expose=True` when adding your feature. Features that have `api_expose` will
be included in the results of the organization details response.

### Add your feature to the FeatureManager

If you want to back your feature flag via options, you can do so using the [Flagpole](/feature-flags/flagpole/) library
by adding the feature to the `FeatureManager` with the `FLAGPOLE` enum set as the feature strategy:

```python
default_manager.add('organizations:test-feature', OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE)
default_manager.add('organizations:test-feature', OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
```

_Note:_ It used to be required to add a new feature's name to `server.py` in Sentry in order to set a default value, but this
is no longer required. Instead, the `manager.add()` method takes a default value, or automatically sets the value
to `False` if no default is provided.
When defining a feature you can also set the default state of the feature flag.
If no default is provided, `False` will be used.

```python
# Example of a feature set with a default value of True
default_manager.add('organizations:test-feature', OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, default=True)
default_manager.add('organizations:test-feature', OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, default=True, api_expose=True)
```

If you don't plan to use Flagpole, use `FeatureHandlerStrategy.INTERNAL` with a custom feature handler instead, for example:
Expand Down Expand Up @@ -130,9 +137,8 @@ our `'organizations:test-feature'` becomes `'test-feature'`.

### In JavaScript

There is a difference between using the flag in Sentry and in GetSentry. At this
stage you're not quite ready to use your feature flag in GetSentry, but you are
able to use it inside Sentry.
In order to check a feature flag in JavaScript, your feature flag will need
`api_expose=True`.

### Declarative features with the Feature component

Expand Down Expand Up @@ -177,7 +183,6 @@ configuration file:
SENTRY_FEATURES['organizations:test-feature'] = True
```


Alternatively, you can test Flagpole features by setting custom options locally.
See the [Flagpole Local Development](/feature-flags/flagpole/#testing-a-flagpole-feature-locally) docs for more information on this.

Expand Down Expand Up @@ -209,9 +214,9 @@ sentry.io, you have a few potential paths:
options-automator repositories.
- If the feature will only be available to SaaS customers on specific plans, you
need to add your feature flag to the appropriate plans and update feature
handlers (see below).You should also enable the feature by default in
[`conf/server.py`](https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py)
in sentry to ensure that the feature is available for self-hosted deployments.
handlers (see below). You should also move the feature flag from
`temporary.py` to `permanent.py` and update the default value to enable the
feature in self-hosted instances.

## Getsentry feature handlers

Expand Down
14 changes: 2 additions & 12 deletions develop-docs/development/analytics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,8 @@ analytics.record(

Run the tests that touch the endpoint to ensure everything is Gucci.

### Step 3: Add it to ETL

To also send the analytics event in Amplitude, add the event to this file: [https://github.com/getsentry/etl/blob/master/etl/operators/analytics_events_schema.py](https://github.com/getsentry/etl/blob/master/etl/operators/analytics_events_schema.py)

```jsx
'my_backend_event.sent': { // Needs to match the `type` field in the class you created in step 1
'name': 'My Backend Event', // The event name in Amplitude
'uid_field': 'target_user_id' // Optional. Field name that represents the user id of the event.
},
```

Note that in the future this will change so that by default, all events will go to Amplitude.
### Step 3:
By default, a new event type is aggregated and sent to Amplitude as long as there is a user_id sent along with the event. If you would like to send events unaggregated, refer to [our Amplitude aggregation docs](https://github.com/getsentry/etl/blob/master/documentation/amplitude_analytics.md)

## Route-Based Frontend Analytics

Expand Down
2 changes: 2 additions & 0 deletions develop-docs/development/database-migrations/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ class MyMigrationTest(TestMigrations):

To run the test locally, run `pytest` with `--migrations` flag. For example, `pytest -v --migrations tests/getsentry/migrations/test_0XXX_migration_name.py`.

If you would like to speed up the migration tests and do not require rebuilding the databases on each test run, supply `--reuse-db` as an additional option to the test command.

### Backup Testing
When you add or change a model, an error message in CI may appear explaining that one or multiple tests "produced an `export.json` backup file that was missing the above models".
In order to resolve this, there are two steps:
Expand Down
2 changes: 2 additions & 0 deletions develop-docs/development/workflow.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ We're slowly working to add typing to our Python codebase, using `mypy` to check
- Check that the file you're modifying is not on the exclude list from `pyproject.toml`. In other words, you need to opt-in the file for type checking to happen.

- To test types locally, you can run `mypy path/to/file` or just `mypy` to run against all files.

- To automatically run `mypy` during pre-push, export the `SENTRY_MYPY_PRE_PUSH` environment variable set to `1`.
42 changes: 42 additions & 0 deletions develop-docs/sdk/envelopes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,48 @@ details.

*None*

### Replay Event

Item type `"replay_event"` contains a replay payload encoded in JSON.

See the <Link to="/sdk/replays/">replays</Link> documentation for the payload
details.

**Constraints:**

- This Item may occur at most once per Envelope.
- This Item must be sent with a Replay Recording Item.

**Envelope Headers:**

*None*

**Additional Item Headers:**

*None*

### Replay Recording

Item type `"replay_recording"` contains a replay recording payload encoded in JSON *or* a gzipped JSON.

See the <Link to="/sdk/replays/">replays</Link> documentation for the payload
details.

**Constraints:**

- This Item may occur at most once per Envelope.
- This Item must be sent with a Replay Recording Item.

**Envelope Headers:**

*None*

**Additional Item Headers:**

`length`

: **integer, required.** The size of the Replay recording payload

### Profile

Item type `"profile"`. This Item contains a profile payload encoded
Expand Down
35 changes: 35 additions & 0 deletions develop-docs/sdk/event-payloads/contexts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,10 @@ If a platform doesn't provide capabilities to identify whether a permission has

_Optional_. A list of visible UI screens at the current point in time.

`start_type`

: _Optional_. The way the OS started the app. For example, `cold`, `warm`, `cold.prewarmed`, or `warm.prewarmed`.

## Browser Context

Browser context carries information about the browser or user agent for
Expand Down Expand Up @@ -811,3 +815,34 @@ This is mostly set on transactions in a web server environment where one transac
}
}
```

## Missing Instrumentation Context

Context contains information about missing or failed OTEL instrumentation.

The required field is `package` which should contain the package or framework where a missing instrumentation was detected.

`package`

: **Required.** The package or framework where a missing instrumentation was detected.

- Example: `express`

`javascript.is_cjs`

: _Optional_. Boolean that indicates if the context was added from a commonjs module.

- Example: `true`

### Example Response Context

```json
{
"contexts": {
"missing_instrumentation": {
"package": "express",
"javascript.is_cjs": true,
}
}
}
```
Loading

0 comments on commit 203f2ad

Please sign in to comment.