Skip to content

Commit 5404b49

Browse files
committed
Merge remote-tracking branch 'origin/master' into sentry-in-ai
* origin/master: docs(sdk): coordination and maintenance standards (#16463) docs(sdk): add spec format components and migrate check-ins (#16461) docs(sdk): repository and documentation standards (#16462) docs(sdk): Add issue saved replies and simplify CopyableCard (#16459) docs(sdk): add review & ci standard (#16458) fix(unity): correct lifecycle breadcrumbs docs (#16456) docs(sdk): add code quality standard (#16455) docs(sdk): migrate releases process to playbook and standard (#16447) docs(sdk): merge basics.mdx into overview.mdx (#16446) docs(sdk): remove old triaging process page (#16448) docs(dart): Update stacktrace info for the logging integration (#16401) docs(dart): Fix user attributes gated behind `sendDefaultPii` (#16407) feat(playstation): Add symbols documentation for dumps (#16454) feat(develop-docs): Restore Sentry Voice guidelines page (#16453) # Conflicts: # app/[[...path]]/page.tsx
2 parents 98c7dba + 1e6af51 commit 5404b49

30 files changed

Lines changed: 1790 additions & 528 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ public/mdx-images/*
9191
public/og-images/*
9292
!public/og-images/README.md
9393

94+
# Ignore LLM plans
95+
/docs/plans/
96+
9497
# yalc
9598
.yalc
9699
yalc.lock

app/[[...path]]/page.tsx

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import {Home} from 'sentry-docs/components/home';
1111
import {Include} from 'sentry-docs/components/include';
1212
import {PageLoadMetrics} from 'sentry-docs/components/pageLoadMetrics';
1313
import {PlatformContent} from 'sentry-docs/components/platformContent';
14+
import {SpecChangelog} from 'sentry-docs/components/specChangelog';
15+
import {isSpecStatus} from 'sentry-docs/components/specConstants';
16+
import {SpecMeta} from 'sentry-docs/components/specMeta';
1417
import {
1518
DocNode,
1619
getCurrentPlatformOrGuide,
@@ -47,25 +50,58 @@ export async function generateStaticParams() {
4750
export const dynamicParams = false;
4851
export const dynamic = 'force-static';
4952

50-
const mdxComponentsWithWrapper = {
51-
...mdxComponents(
52-
{Include, PlatformContent},
53-
({children, frontMatter, nextPage, previousPage}) => (
53+
function mdxComponentsForFrontMatter(frontMatter: Record<string, unknown>) {
54+
const specOverrides: Record<string, unknown> = {};
55+
const changelog = Array.isArray(frontMatter.spec_changelog)
56+
? (frontMatter.spec_changelog as Array<Record<string, unknown>>)
57+
.filter(
58+
entry => entry.version != null && entry.date != null && entry.summary != null
59+
)
60+
.map(entry => ({
61+
version: String(entry.version),
62+
date:
63+
entry.date instanceof Date
64+
? entry.date.toISOString().split('T')[0]
65+
: String(entry.date),
66+
summary: String(entry.summary),
67+
}))
68+
: undefined;
69+
if (changelog && changelog.length > 0) {
70+
specOverrides.SpecChangelog = function () {
71+
return <SpecChangelog changelog={changelog} />;
72+
};
73+
}
74+
if (frontMatter.spec_version && isSpecStatus(frontMatter.spec_status)) {
75+
const boundProps = {
76+
version: String(frontMatter.spec_version),
77+
status: frontMatter.spec_status,
78+
};
79+
specOverrides.SpecMeta = function () {
80+
return <SpecMeta {...boundProps} />;
81+
};
82+
}
83+
return mdxComponents(
84+
{Include, PlatformContent, ...specOverrides},
85+
({children, frontMatter: fm, nextPage, previousPage}) => (
5486
<DocPage
55-
frontMatter={frontMatter}
87+
frontMatter={fm}
5688
nextPage={nextPage}
5789
previousPage={previousPage}
58-
fullWidth={frontMatter.fullWidth}
90+
fullWidth={fm.fullWidth}
5991
>
6092
{children}
6193
</DocPage>
6294
)
63-
),
64-
};
95+
);
96+
}
6597

6698
function MDXLayoutRenderer({mdxSource, ...rest}) {
6799
const MDXLayout = useMemo(() => getMDXComponent(mdxSource), [mdxSource]);
68-
return <MDXLayout components={mdxComponentsWithWrapper} {...rest} />;
100+
const components = useMemo(
101+
() => mdxComponentsForFrontMatter(rest.frontMatter || {}),
102+
[rest.frontMatter]
103+
);
104+
return <MDXLayout components={components} {...rest} />;
69105
}
70106

71107
export default async function Page(props: {params: Promise<{path?: string[]}>}) {
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: Content & Voice
3+
sidebar_order: 25
4+
---
5+
6+
There are two different ways to write copy within the Sentry app. There's normal **plain speech**, and there's our branded, personality-rich "**Sentry Voice**." Sentry Voice is a little snarky (but never mean), jokey, and quick-witted. The jokes should be simple, if it needs explanation, it isn't gonna work.
7+
8+
Generally, you should default to plain and clear speech in the product. This includes page names, table headings, widgets, CTAs, Seer responses, and descriptive text. Occasionally it will be appropriate to use the "Sentry Voice," like on 404 pages, new product announcements and other areas that don't directly interfere with someone's workflow. Within the product, assume users are frustrated and in a hurry — above all our goal is to make sure they can find what they are looking for quickly, and explain what is happening clearly.
9+
10+
### Examples
11+
12+
**Plain speech**
13+
14+
> Issues are groups of errors that have a similar stacktrace. Set an alert for new issues, when an issue changes state, frequency of errors, or users affected by an issue.
15+
16+
**Sentry Voice**
17+
18+
> 404, Page not found. We looked. And then we gave up. [Button: *Return to a Real Page*]
19+
20+
> Sentry Rollback is here. Forgot everything you did this year? Don't worry—we have the receipts. Take a look back at your 2024 with Sentry.
21+
22+
## When to Use "Sentry Voice" vs. Plain Speech
23+
24+
**Do** use Sentry Voice for…
25+
26+
- Designing a new product tour
27+
- Descriptions in the "What's New" feature
28+
- Adding personality to a long (30+ second) loading state
29+
- High level loading states (404, 500, This Page Does Not Exist)
30+
- Onboarding, but use it sparingly. Make sure it is not getting in the way of helping users actually configure their account.
31+
- Empty states, also case-dependent. These should always have an actionable first line, but can have a snarky heading or second sentence.
32+
33+
**Don't** use Sentry Voice (and use plain speech instead) for…
34+
35+
- Product UI. This includes page titles, labels, filters, search, table headings, CTAs, toasts, alerts, and callouts.
36+
- Non-marketing emails. Emails generated by weekly summaries or alerts should be straightforward and direct.
37+
- Settings pages. These are already complicated enough.
38+
- Documentation. Users are here to find information quickly and they need to be easily searchable.
39+
40+
## Writing in "Sentry Voice"
41+
42+
You should not be using this voice within regular workflows, or when someone is trying to complete a task. Even when using Sentry Voice make sure to front-load main information, and not let personality get in the way of content. For example in an error message, make sure the first few words of the body capture the problem first (_404 Page not found_. We looked. And then we gave up.).
43+
44+
Here are three things to keep in mind when writing with personality on behalf of Sentry:
45+
46+
1. **We have empathy for our users**: they should feel understood and like we appropriately grasp the gravity of their situation. Whatever they're going through, we get it. When we are snarky we are snarky towards the situation they are in, not towards the user themself.
47+
2. **We're self-aware**: look, we know were not curing cancer over here. We help developers, but we're not changing the world. Don't make bold claims with aspirational copy.
48+
3. **We have fun**: this stuff is dry, so look for opportunity to have fun with the copy (while keeping everything above in mind).
49+
4. **If you feel confused or unsure where and how to use Sentry Voice, ask our in-house copy writer in the `#discuss-design` Slack channel.**
50+
51+
<Alert>
52+
If you're looking for more information, this was modified from the <a href="https://brand.getsentry.com/document/5#/style-guides/writing-style-guide">brand identity writing style guide</a>.
53+
</Alert>
54+
55+
## General Copywriting Guidelines
56+
57+
**Keep it simple**&mdash;avoid jargon and don't get fancy. If you are referencing new words or concepts explain them or link out to documentation.
58+
59+
**Be informative**. Always provide straightforward, accurate information, we don't manipulate people into believing we're anything more than we actually are.
60+
61+
**Use American spelling**. Apologies to our colleagues who prefer the Queen's English.
62+
63+
**Avoid emotional punctuation**; for example use `!` sparingly.
64+
65+
**Don't use weird punctuation** like the interrobang ``. Not everyone shares your affinity for esoteric glyphs.
66+
67+
**Be consistent.** Reference our [Icons + CTA Copy Table](https://sentry.sentry.io/stories/core/button#icons) to make sure you are using agreed upon terms in CTA Buttons.
68+
For example, Dashboards, Views, Monitors, and Automations are always "Edited" and use the pencil icon.
69+
When a user is creating a new Dashboard, View, or Monitor, the language should always be "Create [Object]" with a plus icon.
70+
71+
**Use punctuation thoughtfully**. If you don't know how to use colons `:` or semicolons `;` it is better not to try. Alternatively, ask a copywriter for help.
72+
73+
<Alert>
74+
<strong>A brief aside on dashes</strong>
75+
76+
Hyphens, the `-` or `&hyphen;` symbol, are used to join words together or write compound numbers (_sixty-five_, _self-serve_).
77+
78+
En-dashes, the `` or `&ndash;` symbol, are most commonly used for time ranges (_2020–2022_, _September 1–September 3)_.
79+
Insert these without a space on either side.
80+
81+
Em-dashes, the `` or `&mdash;` symbol, are the longest of the three and act more like true punctuation.
82+
You can use these in place of a comma or parentheses, or to indicate when a sentence is taking a new turn.
83+
(_We want to introduce users to Seer&mdash;a new name for our old AI product&mdash;which we have rebranded this month_.)
84+
85+
For additional information, refer to <a href="https://www.merriam-webster.com/grammar/em-dash-en-dash-how-to-use">Merriam Webster</a>.
86+
</Alert>
87+
88+
## Use Title Case for Titles and Headings
89+
90+
Within the app we use title case for all headings, CTAs and labels (including: chart titles, table, chart axes, chart legends, table titles, table column headers, form fields labels, anything in the sidebar).
91+
This means the first letter of every word is capitalized, except for conjunctions and "minor" words.
92+
93+
This is true for `<Heading>`, as well as all CTAs, table headers, and default widgets. As a rule, we **never** use all caps in the product. If you see `text-transform: uppercase` anywhere, you should remove it.
94+
95+
**Examples**
96+
97+
> Last Seen (column header)
98+
99+
> Save As… (CTA Button)
100+
101+
> Errors and Outages (sidebar item & H1)
102+
103+
> Most Frozen Frames (default widget title)
104+
105+
Not sure how to convert something? Refer to [capitalizemytitle.com](https://capitalizemytitle.com/) for a quick gut check.

develop-docs/sdk/foundations/overview.mdx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ description: What an SDK is, what it does, and how end-users interact with it.
44
sidebar_order: 1
55
---
66

7+
<Alert>
8+
This document uses key words such as "MUST", "SHOULD", and "MAY" as defined in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) to indicate requirement levels.
9+
</Alert>
10+
711
## Writing an SDK
812

913
At its core an SDK is a set of utilities for capturing data about an exceptional state in an application. Given this data, it then builds and sends a JSON payload to the Sentry server.
@@ -89,3 +93,55 @@ a basic message or exception:
8993

9094
- `Sentry.captureMessage(message)`
9195
- `Sentry.captureException(exception)`
96+
97+
## Run a Local Relay
98+
99+
You do not need a local Sentry instance for SDK development, but you will want to run a local
100+
[relay](https://docs.sentry.io/product/relay/). The reason for this is that Sentry's
101+
main ingestion endpoint is not intended for development but for high throughput
102+
production use. What this means is that a lot of the event processing is happening
103+
after the event has already been accepted by the system so you won't be able to see
104+
errors when sending the HTTP request.
105+
106+
If you haven't used relay yet, have a look at the [getting started](https://docs.sentry.io/product/relay/getting-started/)
107+
docs for relay. Once installed you will want to turn up the log level in your
108+
`.relay/config.yml` file:
109+
110+
```yaml
111+
logging:
112+
level: trace
113+
```
114+
115+
Make sure your relay is running whenever you're doing development:
116+
117+
```shell
118+
relay run
119+
```
120+
121+
When sending events just substitute `orgXXX.ingest.sentry.io` with `localhost:3000` or
122+
whichever port you chose. Also note that a local relay will out of the box
123+
be available via HTTP only so don't try to send HTTPS requests there.
124+
125+
## Consult Existing SDKs
126+
127+
While we're trying to keep the docs up to date about all important things, it's usually
128+
a good idea to refer to already existing Sentry SDKs for input. In particular the
129+
transport design is not part of the documentation but generally quite similar between
130+
SDKs.
131+
132+
## Define Conventions and Types Before Shipping
133+
134+
Before shipping new or changed SDK behavior, make sure the relevant definitions exist outside your SDK first:
135+
136+
- **Semantic conventions:** New or changed attributes **MUST** first be defined in [sentry-conventions](https://github.com/getsentry/sentry-conventions/). If the convention you need doesn't exist yet, open a PR there to propose it. Only after the convention has been merged should you implement it in an SDK. This ensures all SDKs use consistent naming and semantics.
137+
138+
The merge process for sentry-conventions PRs:
139+
1. Open a PR with the proposed convention.
140+
2. Get an approval from at least one code owner.
141+
3. Wait at least 3 business days after the first approval to give other code owners a chance to review.
142+
143+
- **Context types:** Any newly added [context](https://develop.sentry.dev/sdk/foundations/data-model/event-payloads/contexts/) **SHOULD** also be typed out in [Relay](https://github.com/getsentry/relay/tree/master/relay-event-schema/src/protocol/contexts) so that the schema stays in sync with what SDKs emit.
144+
145+
## Join us on Discord
146+
147+
You can reach out to Sentry open source contributors and talk with other SDK maintainers on the [Sentry Discord server](https://discord.gg/sentry).
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
title: Setting Up Release Infrastructure
3+
---
4+
5+
## Steps
6+
7+
#### 1. Create the Initial Tag
8+
9+
A tag must exist for the first commit of the repository due to a [craft limitation](https://github.com/getsentry/craft/issues/342). Tag the first commit before any meaningful history so the first changelog includes useful context.
10+
11+
```bash
12+
git tag 0.0.0 "$(git log -1 --reverse --format=%h)"
13+
git push origin --tags
14+
```
15+
16+
#### 2. Set Up CI for Release Branches
17+
18+
Ensure the repository's CI responds to `release/**` branches and produces a named artifact. See [sentry-python's build workflow](https://github.com/getsentry/sentry-python/blob/master/.github/workflows/build.yml) for an example.
19+
20+
#### 3. Configure Craft (`.craft.yml`)
21+
22+
Create a `.craft.yml` with targets for your package registry and GitHub releases:
23+
24+
```yaml
25+
minVersion: 0.28.1
26+
targets:
27+
- name: pypi
28+
- name: github
29+
```
30+
31+
See the [Craft configuration docs](https://craft.sentry.dev/configuration/) for all available targets and options.
32+
33+
#### 4. Add Version Bump Script (`scripts/bump-version.sh`)
34+
35+
Craft invokes this script when bumping the version. The script receives the old version as `$1` and the new version as `$2`:
36+
37+
```bash
38+
#!/usr/bin/env bash
39+
set -euxo pipefail
40+
41+
sed -i "s/^version =.*/version = $2/" setup.cfg
42+
```
43+
44+
For a real-world example with multiple version locations, see [sentry-python's bump-version.sh](https://github.com/getsentry/sentry-python/blob/master/scripts/bump-version.sh).
45+
46+
#### 5. Add Release Workflow (`.github/workflows/release.yml`)
47+
48+
This workflow triggers releases from the GitHub UI. It uses `vars.SENTRY_RELEASE_BOT_CLIENT_ID` and `secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY` which are available to repositories in the `getsentry` org automatically. These are needed because [GitHub prevents `GITHUB_TOKEN` from triggering downstream workflows](https://docs.github.com/en/actions/reference/events-that-trigger-workflows).
49+
50+
```yaml
51+
name: Release
52+
53+
on:
54+
workflow_dispatch:
55+
inputs:
56+
version:
57+
description: Version to release
58+
required: false
59+
force:
60+
description: Force a release even when there are release-blockers (optional)
61+
required: false
62+
63+
jobs:
64+
release:
65+
runs-on: ubuntu-latest
66+
name: "Release a new version"
67+
steps:
68+
- name: Get auth token
69+
id: token
70+
uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
71+
with:
72+
app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }}
73+
private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }}
74+
- uses: actions/checkout@v6
75+
with:
76+
token: ${{ steps.token.outputs.token }}
77+
fetch-depth: 0
78+
- name: Prepare release
79+
uses: getsentry/craft@v2
80+
env:
81+
GITHUB_TOKEN: ${{ steps.token.outputs.token }}
82+
with:
83+
version: ${{ github.event.inputs.version }}
84+
force: ${{ github.event.inputs.force }}
85+
```
86+
87+
For full details on all available options including auto-versioning, changelog preview, merge targets, and multiple craft configs, see [Craft's GitHub Actions documentation](https://craft.sentry.dev/github-actions/). Repositories outside the `getsentry` org can use the simpler [reusable workflow](https://craft.sentry.dev/github-actions/#option-1-reusable-workflow-recommended) which handles token management automatically via `secrets: inherit`.
88+
89+
#### 6. Set Repository Permissions
90+
91+
Give the `engineering` team write access via your repository's settings page: `https://github.com/getsentry/REPONAME_HERE/settings/access`
92+
93+
#### 7. Create Branch Ruleset
94+
95+
Download the [default ruleset template](/json/Default_ruleset.json). Import it at `https://github.com/getsentry/REPONAME_HERE/settings/rules` via **New ruleset** > **Import a ruleset**. You can adjust settings but do not remove the App in the Bypass List.
96+
97+
#### 8. Cut Your First Release
98+
99+
Navigate to the Actions tab, locate the Release workflow, and trigger it. This creates an [issue in `getsentry/publish`](https://github.com/getsentry/publish/issues) which requires an approver to add a label before artifacts are published.
100+
101+
For the ongoing release process after setup, see "Cutting a release" (wip).
102+
103+
## Referenced Standards
104+
105+
- [Version format](/sdk/getting-started/standards/release-versioning#version-format)
106+
- [Release tooling](/sdk/getting-started/standards/release-versioning#release-tooling)
107+
- Release gating criteria (wip)
108+
- Rollback procedures (wip)

0 commit comments

Comments
 (0)