Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,79 @@ describe('javascript-ember onboarding docs', () => {
).toBeInTheDocument();
expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();

// Includes import statement in multiple places
expect(
screen.getAllByText(
textWithMarkupMatcher(/import \* as Sentry from "@sentry\/ember"/)
)
).toHaveLength(2); // Appears in configure and verify steps
screen.getByText(textWithMarkupMatcher(/import \* as Sentry from "@sentry\/ember"/))
).toBeInTheDocument();
});

it('initializes the SDK directly and loads application initializers', () => {
renderWithOnboardingLayout(docs);

const setup = screen.getByText(textWithMarkupMatcher(/Sentry\.init\(/));
expect(setup).toHaveTextContent('import config from "./config/environment"');
expect(setup).toHaveTextContent('loadInitializers(App, config.modulePrefix)');
expect(setup).toHaveTextContent('dataCollection:');
expect(setup).not.toHaveTextContent(/sendDefaultPii|enableLogs|enableMetrics/);
});

it('registers a performance instance initializer when tracing is selected', () => {
renderWithOnboardingLayout(docs, {
selectedProducts: [ProductSolution.PERFORMANCE_MONITORING],
});

const initializer = screen.getByText(
textWithMarkupMatcher(/export function initialize\(appInstance\)/)
);
expect(initializer).toHaveTextContent(
'import { instrumentAppInstancePerformance } from "@sentry/ember"'
);
expect(initializer).toHaveTextContent(
'instrumentAppInstancePerformance(appInstance)'
);
expect(initializer).toHaveTextContent('export default { initialize }');
});

it('omits performance instrumentation when tracing is not selected', () => {
renderWithOnboardingLayout(docs, {
selectedProducts: [ProductSolution.ERROR_MONITORING],
});

expect(
screen.queryByText(textWithMarkupMatcher(/instrumentAppInstancePerformance/))
).not.toBeInTheDocument();
expect(
screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
).not.toBeInTheDocument();
});

it('verifies errors with a component action and button', () => {
renderWithOnboardingLayout(docs, {
selectedProducts: [ProductSolution.ERROR_MONITORING],
});

const component = screen.getByText(textWithMarkupMatcher(/throw new Error/));
expect(component).toHaveTextContent('extends Component');
expect(component).toHaveTextContent(/@action\s*triggerError\(\)/);
expect(component).not.toHaveTextContent(/setTimeout|@sentry\/ember/);
expect(
screen.getByText(textWithMarkupMatcher(/\{\{on "click" this\.triggerError\}\}/))
).toHaveTextContent('Break the world');
});

it('sends both selected signals before the verification error', () => {
renderWithOnboardingLayout(docs, {
selectedProducts: [
ProductSolution.ERROR_MONITORING,
ProductSolution.LOGS,
ProductSolution.METRICS,
],
});

const component = screen.getByText(textWithMarkupMatcher(/throw new Error/));
expect(component).toHaveTextContent('import * as Sentry from "@sentry/ember"');
expect(component).toHaveTextContent(
/Sentry\.logger\.info.*Sentry\.metrics\.count.*throw new Error/
);
});

it('displays sample rates by default', () => {
Expand Down
87 changes: 73 additions & 14 deletions static/app/gettingStartedDocs/javascript-ember/onboarding.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
ContentBlock,
DocsParams,
OnboardingConfig,
} from 'sentry/components/onboarding/gettingStartedDoc/types';
Expand All @@ -10,30 +11,37 @@ import {getSdkSetupSnippet, installSnippetBlock} from './utils';

const getVerifyEmberSnippet = (params: DocsParams) => {
const logsCode = params.isLogsSelected
? `// Send a log before throwing the error
Sentry.logger.info(Sentry.logger.fmt\`User \${"sentry-test"} triggered test error button\`, {
action: "test_error_button_click",
? ` // Send a log before throwing the error
Sentry.logger.info('User triggered test error', {
action: 'test_error_button_click',
});
`
: '';

const metricsCode = params.isMetricsSelected
? `// Send a test metric before throwing the error
? ` // Send a test metric before throwing the error
Sentry.metrics.count('test_counter', 1);
`
: '';

return `
import * as Sentry from "@sentry/ember";

setTimeout(() => {
${logsCode}${metricsCode}throw new Error("Sentry Test Error");
});`;
return `import Component from "@glimmer/component";
import { action } from "@ember/object";
${
params.isLogsSelected || params.isMetricsSelected
? 'import * as Sentry from "@sentry/ember";\n'
: ''
}
export default class SentryTestComponent extends Component {
@action
triggerError() {
${logsCode}${metricsCode} throw new Error("Sentry Test Error");
}
}`;
};

export const onboarding: OnboardingConfig = {
introduction: () =>
tct("In this quick guide you'll use [strong:npm] or [strong:yarn] to set up:", {
tct("In this quick guide you'll use the [strong:Ember CLI] to set up:", {
strong: <strong />,
}),
install: () => [
Expand All @@ -57,7 +65,7 @@ export const onboarding: OnboardingConfig = {
{
type: 'text',
text: tct(
'You should [code:init] the Sentry SDK as soon as possible during your application load up in [code:app.js], before initializing Ember:',
'Initialize Sentry in [code:app/app.js], before the Application class. Keep the [code:loadInitializers] call so Ember loads your initializers:',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: I think we don't need to change anything in the onboarding config. The only relevant changes are the small updates to the verify script.

There's no need to call out the loadInitializers or reword the sentence we had before.

{
code: <code />,
}
Expand All @@ -69,10 +77,39 @@ export const onboarding: OnboardingConfig = {
{
label: 'JavaScript',
language: 'javascript',
filename: 'app/app.js',
code: getSdkSetupSnippet(params),
},
],
},
...((params.isPerformanceSelected
? [
{
type: 'text',
text: tct(
'To enable tracing, create [code:app/instance-initializers/sentry-performance.js]. The v2 addon does not register performance instrumentation automatically:',
{code: <code />}
),
},
{
type: 'code',
tabs: [
{
label: 'JavaScript',
language: 'javascript',
filename: 'app/instance-initializers/sentry-performance.js',
code: `import { instrumentAppInstancePerformance } from "@sentry/ember";

export function initialize(appInstance) {
instrumentAppInstancePerformance(appInstance);
}

export default { initialize };`,
},
],
},
]
: []) satisfies ContentBlock[]),
],
},
getUploadSourceMapsStep({
Expand All @@ -86,8 +123,9 @@ export const onboarding: OnboardingConfig = {
content: [
{
type: 'text',
text: t(
"This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
text: tct(
'Create a [code:SentryTest] component with the following class and template:',
{code: <code />}
),
},
{
Expand All @@ -96,10 +134,31 @@ export const onboarding: OnboardingConfig = {
{
label: 'JavaScript',
language: 'javascript',
filename: 'app/components/sentry-test.js',
code: getVerifyEmberSnippet(params),
},
],
},
{
type: 'code',
tabs: [
{
label: 'Handlebars',
language: 'html',
filename: 'app/components/sentry-test.hbs',
code: `<button type="button" {{on "click" this.triggerError}}>
Break the world
</button>`,
},
],
},
{
type: 'text',
text: tct(
'Render [code:<SentryTest />] in an application template, then click "Break the world" to send a test error to Sentry. If you selected Logs or Metrics, clicking the button sends those too.',
{code: <code />}
),
},
],
},
],
Expand Down
4 changes: 3 additions & 1 deletion static/app/gettingStartedDocs/javascript-ember/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const getDynamicParts = (params: DocsParams): string[] => {
if (params.isPerformanceSelected) {
dynamicParts.push(`
// Tracing
tracesSampleRate: 1.0, // Capture 100% of the transactions
tracesSampleRate: 1.0, // Capture 100% of the traces
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/]`);
}
Expand Down Expand Up @@ -91,6 +91,8 @@ export default class App extends Application {
podModulePrefix = config.podModulePrefix;
Resolver = Resolver;
}

loadInitializers(App, config.modulePrefix);
`;
}

Expand Down
Loading