Skip to content

Commit d3dc472

Browse files
authored
feat(onboarding): Add dart onboarding and revamp flutter logs onboarding (#97432)
resolves https://linear.app/getsentry/issue/LOGS-289/add-verify-steps-to-flutter-onboarding I noticed dart doesn't show up in the in-product onboarding, so added it here. Also then updated everything for logs, and cleaned up some of the code/snippets. - Add dart onboarding page to product - Add logs to verify section for flutter onboarding - Add logs and tracing production selection to dart onboarding <img width="3024" height="2834" alt="image" src="https://github.com/user-attachments/assets/392c53c6-efdc-4a5c-a0d3-a7144a735209" /> <img width="3024" height="3302" alt="image" src="https://github.com/user-attachments/assets/b8c516f2-a40f-480c-863e-6981f1b1bd50" />
1 parent ddb21fa commit d3dc472

File tree

6 files changed

+153
-65
lines changed

6 files changed

+153
-65
lines changed

static/app/components/onboarding/productSelection.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export const platformProductAvailability = {
112112
ProductSolution.SESSION_REPLAY,
113113
ProductSolution.LOGS,
114114
],
115+
dart: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.LOGS],
115116
kotlin: [ProductSolution.PERFORMANCE_MONITORING],
116117
go: [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.LOGS],
117118
'go-echo': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.LOGS],

static/app/components/platformPicker.spec.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ describe('PlatformPicker', function () {
7878
'Angular',
7979
'Astro',
8080
'Browser JavaScript',
81+
'Dart',
8182
'Ember',
8283
'Flutter',
8384
'Gatsby',

static/app/data/platformPickerCategories.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const popularPlatformCategories: Set<PlatformKey> = new Set([
3434
]);
3535

3636
const browser: Set<PlatformKey> = new Set([
37+
'dart',
3738
'flutter',
3839
'javascript',
3940
'javascript-angular',
@@ -58,6 +59,7 @@ const browser: Set<PlatformKey> = new Set([
5859

5960
const server: Set<PlatformKey> = new Set([
6061
'bun',
62+
'dart',
6163
'deno',
6264
'dotnet',
6365
'dotnet-aspnet',
@@ -122,6 +124,7 @@ const mobile: Set<PlatformKey> = new Set([
122124
'cordova',
123125
'dotnet-maui',
124126
'dotnet-xamarin',
127+
'dart',
125128
'flutter',
126129
'ionic',
127130
'react-native',
@@ -136,6 +139,7 @@ const desktop: Set<PlatformKey> = new Set([
136139
'dotnet-winforms',
137140
'dotnet-wpf',
138141
'electron',
142+
'dart',
139143
'flutter',
140144
'godot',
141145
'java',

static/app/gettingStartedDocs/dart/dart.tsx

Lines changed: 102 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {
33
Docs,
44
DocsParams,
55
OnboardingConfig,
6+
OnboardingStep,
67
} from 'sentry/components/onboarding/gettingStartedDoc/types';
78
import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/types';
89
import {
@@ -16,7 +17,7 @@ type Params = DocsParams;
1617

1718
const getInstallSnippet = (params: Params) => `
1819
dependencies:
19-
sentry: ^${getPackageVersion(params, 'sentry.dart', '7.8.0')}`;
20+
sentry: ^${getPackageVersion(params, 'sentry.dart', '9.6.0')}`;
2021

2122
const getConfigureSnippet = (params: Params) => `
2223
import 'package:sentry/sentry.dart';
@@ -26,30 +27,48 @@ Future<void> main() async {
2627
options.dsn = '${params.dsn.public}';
2728
// Adds request headers and IP for users,
2829
// visit: https://docs.sentry.io/platforms/dart/data-management/data-collected/ for more info
29-
options.sendDefaultPii = true;
30+
options.sendDefaultPii = true;${
31+
params.isLogsSelected
32+
? `
33+
// Enable logs to be sent to Sentry
34+
options.enableLogs = true;`
35+
: ''
36+
}${
37+
params.isPerformanceSelected
38+
? `
3039
// Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
3140
// We recommend adjusting this value in production.
32-
options.tracesSampleRate = 1.0;
41+
options.tracesSampleRate = 1.0;`
42+
: ''
43+
}
3344
});
3445
3546
// or define SENTRY_DSN via Dart environment variable (--dart-define)
3647
}`;
3748

38-
const getVerifySnippet = () => `
49+
const getVerifySnippet = (params: Params) => {
50+
const logsCode = params.isLogsSelected
51+
? `
52+
// Send a log before throwing the error
53+
Sentry.logger.info("User triggered test error", {
54+
'action': SentryLogAttribute.string('test_error'),
55+
});`
56+
: '';
57+
return `
3958
import 'package:sentry/sentry.dart';
4059
41-
try {
60+
try {${logsCode}
4261
aMethodThatMightFail();
4362
} catch (exception, stackTrace) {
4463
await Sentry.captureException(
4564
exception,
4665
stackTrace: stackTrace,
4766
);
4867
}`;
68+
};
4969

5070
const getPerfomanceSnippet = () => `
5171
import 'package:sentry/sentry.dart';
52-
import { getPackageVersion } from 'sentry/utils/gettingStartedDocs/getPackageVersion';
5372
5473
final transaction = Sentry.startTransaction('processOrderBatch()', 'task');
5574
@@ -115,46 +134,83 @@ const onboarding: OnboardingConfig = {
115134
],
116135
},
117136
],
118-
verify: () => [
119-
{
120-
type: StepType.VERIFY,
121-
description: t(
122-
'Create an intentional error, so you can test that everything is working:'
123-
),
124-
configurations: [
125-
{
126-
language: 'dart',
127-
code: getVerifySnippet(),
128-
additionalInfo: tct(
129-
"If you're new to Sentry, use the email alert to access your account and complete a product tour.[break] If you're an existing user and have disabled alerts, you won't receive this email.",
130-
{
131-
break: <br />,
132-
}
133-
),
134-
},
135-
],
136-
},
137-
{
138-
title: t('Tracing'),
139-
description: t(
140-
"You'll be able to monitor the performance of your app using the SDK. For example:"
141-
),
142-
configurations: [
143-
{
144-
language: 'dart',
145-
code: getPerfomanceSnippet(),
146-
additionalInfo: tct(
147-
'To learn more about the API and automatic instrumentations, check out the [perfDocs: performance documentation].',
148-
{
149-
perfDocs: (
150-
<ExternalLink href="https://docs.sentry.io/platforms/dart/tracing/instrumentation/" />
151-
),
152-
}
153-
),
154-
},
155-
],
156-
},
157-
],
137+
verify: params => {
138+
const steps: OnboardingStep[] = [
139+
{
140+
type: StepType.VERIFY,
141+
description: t(
142+
'Create an intentional error, so you can test that everything is working:'
143+
),
144+
configurations: [
145+
{
146+
language: 'dart',
147+
code: getVerifySnippet(params),
148+
additionalInfo: tct(
149+
"If you're new to Sentry, use the email alert to access your account and complete a product tour.[break] If you're an existing user and have disabled alerts, you won't receive this email.",
150+
{
151+
break: <br />,
152+
}
153+
),
154+
},
155+
],
156+
},
157+
];
158+
159+
if (params.isPerformanceSelected) {
160+
steps.push({
161+
title: t('Tracing'),
162+
description: t(
163+
"You'll be able to monitor the performance of your app using the SDK. For example:"
164+
),
165+
configurations: [
166+
{
167+
language: 'dart',
168+
code: getPerfomanceSnippet(),
169+
additionalInfo: tct(
170+
'To learn more about the API and automatic instrumentations, check out the [perfDocs: performance documentation].',
171+
{
172+
perfDocs: (
173+
<ExternalLink href="https://docs.sentry.io/platforms/dart/tracing/instrumentation/" />
174+
),
175+
}
176+
),
177+
},
178+
],
179+
});
180+
}
181+
182+
return steps;
183+
},
184+
nextSteps: params => {
185+
const steps = [
186+
{
187+
name: t('Upload Debug Symbols'),
188+
description: t(
189+
'We offer a range of methods to provide Sentry with debug symbols so that you can see symbolicated stack traces and find the cause of your errors faster.'
190+
),
191+
link: 'https://docs.sentry.io/platforms/flutter/upload-debug/',
192+
},
193+
{
194+
name: t('Connect your Git Repo'),
195+
description: t(
196+
'Adding our Git integrations will allow us determine suspect commits, comment on PRs, and create links directly to your source code from Sentry issues.'
197+
),
198+
link: 'https://docs.sentry.io/organization/integrations/source-code-mgmt/',
199+
},
200+
];
201+
202+
if (params.isLogsSelected) {
203+
steps.push({
204+
name: t('Structured Logs'),
205+
description: t(
206+
'Learn how to send structured logs to Sentry and view them alongside your errors.'
207+
),
208+
link: 'https://docs.sentry.io/platforms/dart/logs/',
209+
});
210+
}
211+
212+
return steps;
213+
},
158214
};
159215

160216
export const feedbackOnboardingCrashApiDart: OnboardingConfig = {

static/app/gettingStartedDocs/flutter/flutter.spec.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ describe('flutter onboarding docs', function () {
7575
expect(
7676
await screen.findByText(textWithMarkupMatcher(/options.tracesSampleRate/))
7777
).toBeInTheDocument();
78+
expect(
79+
await screen.findByText(textWithMarkupMatcher(/options\.tracesSampleRate = 1\.0/))
80+
).toBeInTheDocument();
7881
expect(
7982
await screen.findByText(
8083
textWithMarkupMatcher(
@@ -103,6 +106,9 @@ describe('flutter onboarding docs', function () {
103106
expect(
104107
await screen.findByText(textWithMarkupMatcher(/options.profilesSampleRate/))
105108
).toBeInTheDocument();
109+
expect(
110+
await screen.findByText(textWithMarkupMatcher(/options\.profilesSampleRate = 1\.0/))
111+
).toBeInTheDocument();
106112
expect(
107113
await screen.findByText(
108114
textWithMarkupMatcher(/Flutter Profiling alpha is available/)
@@ -128,10 +134,14 @@ describe('flutter onboarding docs', function () {
128134
});
129135

130136
expect(
131-
await screen.findByText(textWithMarkupMatcher(/options.replay.sessionSampleRate/))
137+
await screen.findByText(
138+
textWithMarkupMatcher(/options\.replay\.sessionSampleRate = 0\.1/)
139+
)
132140
).toBeInTheDocument();
133141
expect(
134-
await screen.findByText(textWithMarkupMatcher(/options.replay.onErrorSampleRate/))
142+
await screen.findByText(
143+
textWithMarkupMatcher(/options\.replay\.onErrorSampleRate = 1\.0/)
144+
)
135145
).toBeInTheDocument();
136146
});
137147

@@ -153,6 +163,11 @@ describe('flutter onboarding docs', function () {
153163
await screen.findByText(textWithMarkupMatcher(/options\.enableLogs = true/))
154164
).toBeInTheDocument();
155165

166+
// Should include a log call in the verify snippet
167+
expect(
168+
await screen.findByText(textWithMarkupMatcher(/Sentry\.logger\.info/))
169+
).toBeInTheDocument();
170+
156171
// Should include logging next step
157172
expect(await screen.findByText('Structured Logs')).toBeInTheDocument();
158173
});

static/app/gettingStartedDocs/flutter/flutter.tsx

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const isAutoInstall = (params: Params) =>
4949
params.platformOptions?.installationMode === InstallationMode.AUTO;
5050

5151
const getManualInstallSnippet = (params: Params) => {
52-
const version = getPackageVersion(params, 'sentry.dart.flutter', '8.13.2');
52+
const version = getPackageVersion(params, 'sentry.dart.flutter', '9.6.0');
5353
return `dependencies:
5454
sentry_flutter: ^${version}`;
5555
};
@@ -64,6 +64,19 @@ Future<void> main() async {
6464
// Adds request headers and IP for users,
6565
// visit: https://docs.sentry.io/platforms/dart/data-management/data-collected/ for more info
6666
options.sendDefaultPii = true;${
67+
params.isLogsSelected
68+
? `
69+
// Enable logs to be sent to Sentry
70+
options.enableLogs = true;`
71+
: ''
72+
}${
73+
params.isReplaySelected
74+
? `
75+
// Set sessionSampleRate to 0.1 to capture 10% of sessions and onErrorSampleRate to 1.0 to capture 100% of errors.
76+
options.replay.sessionSampleRate = 0.1;
77+
options.replay.onErrorSampleRate = 1.0;`
78+
: ''
79+
}${
6780
params.isPerformanceSelected
6881
? `
6982
// Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
@@ -77,19 +90,6 @@ Future<void> main() async {
7790
// Setting to 1.0 will profile 100% of sampled transactions:
7891
options.profilesSampleRate = 1.0;`
7992
: ''
80-
}${
81-
params.isReplaySelected
82-
? `
83-
// Set sessionSampleRate to 0.1 to capture 10% of sessions and onErrorSampleRate to 1.0 to capture 100% of errors.
84-
options.replay.sessionSampleRate = 0.1;
85-
options.replay.onErrorSampleRate = 1.0;`
86-
: ''
87-
}${
88-
params.isLogsSelected
89-
? `
90-
// Enable logs to be sent to Sentry
91-
options.enableLogs = true;`
92-
: ''
9393
}
9494
},
9595
appRunner: () => runApp(
@@ -109,14 +109,25 @@ const configureAdditionalInfo = tct(
109109
}
110110
);
111111

112-
const getVerifySnippet = () => `
112+
const getVerifySnippet = (params: Params) => {
113+
const logsCode = params.isLogsSelected
114+
? `
115+
// Send a log before throwing the error
116+
Sentry.logger.info("User triggered test error button", {
117+
'action': SentryLogAttribute.string('test_error_button_click'),
118+
});`
119+
: '';
120+
return `
121+
import 'package:sentry/sentry.dart';
122+
113123
child: ElevatedButton(
114-
onPressed: () {
124+
onPressed: () {${logsCode}
115125
throw StateError('This is test exception');
116126
},
117127
child: const Text('Verify Sentry Setup'),
118128
)
119129
`;
130+
};
120131

121132
const getFeedbackConfigureSnippet = () => `
122133
// The example uses the NavigatorState to present the widget. Adapt as needed to your navigation stack.
@@ -342,7 +353,7 @@ const onboarding: OnboardingConfig<PlatformOptions> = {
342353
label: 'Dart',
343354
value: 'dart',
344355
language: 'dart',
345-
code: getVerifySnippet(),
356+
code: getVerifySnippet(params),
346357
},
347358
],
348359
},

0 commit comments

Comments
 (0)