Skip to content
Open
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
136 changes: 90 additions & 46 deletions .github/workflows/build.yml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import Resolver from 'ember-resolver';
import config from './config/environment';

Sentry.init({
dsn: config.sentryDsn,
tracesSampleRate: 1,
replaysSessionSampleRate: 1,
replaysOnErrorSampleRate: 1,
tracePropagationTargets: ['localhost', 'doesntexist.example'],
Comment thread
cursor[bot] marked this conversation as resolved.
tunnel: `http://localhost:3031/`, // proxy server
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare const config: {
podModulePrefix: string;
locationType: 'history' | 'hash' | 'none' | 'auto';
rootURL: string;
sentryDsn: string;
APP: Record<string, unknown>;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type ApplicationInstance from '@ember/application/instance';
import { addIntegration, browserTracingIntegration } from '@sentry/ember';

export function initialize(appInstance: ApplicationInstance): void {
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.

Hey, I am taking another look over this as we are getting closer to planning the next major, where this could go in.

Ideally, we'd align this more closely with how we handle sentry init in other places as well - which would be, to keep things centralized in Sentry.init(). Is there a way we can make this work reliably? I am thinking of something like this:

// app.ts
export default class App extends Application {
  modulePrefix = config.modulePrefix;
  podModulePrefix = config.podModulePrefix;
  Resolver = Resolver;
}

Sentry.init({
  // ...
  integrations: [
    Sentry.browserTracingIntegration({ emberApp: App })
  ]
});

and somehow derive/wrap the necessary thing inside of this? That would be the ideal solution IMHO, or something along these lines. then we can also get rid of all the async import and special options for performance etc. and just pass this directly to the (ember-specific) browser tracing integration 🤔

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.

Or alternatively, if this cannot be made to work nicely, we could also do this in the initializer, which would be more "sentry native":

import * as Sentry from '@sentry/ember';

export function initialize(appInstance) {
  Sentry.addIntegration(Sentry.browserTracingIntegration({ 
    appInstance,
    // other options here
  }); 
}

this would possibly loose tiny bits of timing info but should overall be likely OK...

Then, we need to export a custom browserTracingIntegration from the ember package here, similar to e.g. the vue browserTracingIntegration, where we can run the actual logic.

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.

I will look into PRing into this PR some changes for this!

addIntegration(browserTracingIntegration({
appInstance,
minimumRunloopQueueDuration: 0,
minimumComponentRenderDuration: 0,
}));
}
Comment thread
aklkv marked this conversation as resolved.

export default {
initialize,
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,7 @@ module.exports = function (environment) {
},
};

ENV['@sentry/ember'] = {
sentry: {
tracesSampleRate: 1,
dsn: process.env.E2E_TEST_DSN,
tracePropagationTargets: ['localhost', 'doesntexist.example'],
browserTracingOptions: {
_experiments: {
// This lead to some flaky tests, as that is sometimes logged
enableLongTask: false,
},
},
},
ignoreEmberOnErrorWarning: true,
minimumRunloopQueueDuration: 0,
minimumComponentRenderDuration: 0,
};
ENV.sentryDsn = process.env.E2E_TEST_DSN;

if (environment === 'development') {
// ENV.APP.LOG_RESOLVER = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import loadInitializers from 'ember-load-initializers';
import Resolver from 'ember-resolver';

Sentry.init({
dsn: config.sentryDsn,
tracesSampleRate: 1,
replaysSessionSampleRate: 1,
replaysOnErrorSampleRate: 1,
tracePropagationTargets: ['localhost', 'doesntexist.example'],
tunnel: `http://localhost:3031/`, // proxy server
});
export default class App extends Application {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare const config: {
podModulePrefix: string;
locationType: 'history' | 'hash' | 'none' | 'auto';
rootURL: string;
sentryDsn: string;
APP: Record<string, unknown>;
};

Expand Down
Comment thread
aklkv marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type ApplicationInstance from '@ember/application/instance';
import { addIntegration, browserTracingIntegration } from '@sentry/ember';

export function initialize(appInstance: ApplicationInstance): void {
addIntegration(browserTracingIntegration({
appInstance,
minimumRunloopQueueDuration: 0,
minimumComponentRenderDuration: 0,
}));
}

export default {
initialize,
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,7 @@ module.exports = function (environment) {
},
};

ENV['@sentry/ember'] = {
sentry: {
tracesSampleRate: 1,
dsn: process.env.E2E_TEST_DSN,
tracePropagationTargets: ['localhost', 'doesntexist.example'],
browserTracingOptions: {
_experiments: {
// This lead to some flaky tests, as that is sometimes logged
enableLongTask: false,
},
},
},
ignoreEmberOnErrorWarning: true,
minimumRunloopQueueDuration: 0,
minimumComponentRenderDuration: 0,
};
ENV.sentryDsn = process.env.E2E_TEST_DSN;

if (environment === 'development') {
// ENV.APP.LOG_RESOLVER = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
/**
Ember CLI sends analytics information by default. The data is completely
anonymous, but there are times when you might want to disable this behavior.

Setting `disableAnalytics` to true will prevent any data from being sent.
*/
"disableAnalytics": true,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# This file is committed to git and should not contain any secrets.
NODE_ENV=development
12 changes: 12 additions & 0 deletions dev-packages/e2e-tests/test-applications/ember-vite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# dependencies
/node_modules/

# build output
/dist/

# misc
/.env*
!/.env.development

# test results
/results.junit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default {
extends: "recommended",
checkHbsTemplateLiterals: false,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"liveReload": false,
"watcher": "node"
}
26 changes: 26 additions & 0 deletions dev-packages/e2e-tests/test-applications/ember-vite/app/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Application from '@ember/application';
import compatModules from '@embroider/virtual/compat-modules';
import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers';
import setupInspector from '@embroider/legacy-inspector-support/ember-source-4.12';
import * as Sentry from '@sentry/ember';

import config from 'ember-vite/config/environment';

Sentry.init({
dsn: config.sentryDsn,
tracesSampleRate: 1,
replaysSessionSampleRate: 1,
replaysOnErrorSampleRate: 1,
tracePropagationTargets: ['localhost', 'doesntexist.example'],
tunnel: `http://localhost:3031/`, // proxy server
});

export default class App extends Application {
modulePrefix = config.modulePrefix;
podModulePrefix = config.podModulePrefix;
Resolver = Resolver.withModules(compatModules);
inspector = setupInspector(this);
}

loadInitializers(App, config.modulePrefix, compatModules);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { on } from '@ember/modifier';

import type { TOC } from '@ember/component/template-only';

interface TestSectionSignature {
Args: {
title: string;
buttonLabel: string;
buttonFunction: () => void;
};
}

const TestSection: TOC<TestSectionSignature> = <template>
<div class="section">
<h4>{{@title}}</h4>
<button type="button" {{on "click" @buttonFunction}} data-test-button={{@title}}>
{{@buttonLabel}}
</button>
</div>
</template>;

export default TestSection;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import loadConfigFromMeta from '@embroider/config-meta-loader';
import { assert } from '@ember/debug';

const config = loadConfigFromMeta('ember-vite') as unknown;

assert('config is not an object', typeof config === 'object' && config !== null);
assert('modulePrefix was not detected on your config', 'modulePrefix' in config && typeof config.modulePrefix === 'string');
assert('locationType was not detected on your config', 'locationType' in config && typeof config.locationType === 'string');
assert('rootURL was not detected on your config', 'rootURL' in config && typeof config.rootURL === 'string');
assert('APP was not detected on your config', 'APP' in config && typeof config.APP === 'object');

export default config as {
modulePrefix: string;
podModulePrefix?: string;
locationType: string;
rootURL: string;
sentryDsn: string;
APP: Record<string, unknown>;
} & Record<string, unknown>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type ApplicationInstance from '@ember/application/instance';
import { addIntegration, browserTracingIntegration } from '@sentry/ember';

export function initialize(appInstance: ApplicationInstance): void {
addIntegration(browserTracingIntegration({
appInstance,
minimumRunloopQueueDuration: 0,
minimumComponentRenderDuration: 0,
}));
}

export default {
initialize,
};
15 changes: 15 additions & 0 deletions dev-packages/e2e-tests/test-applications/ember-vite/app/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import EmberRouter from '@embroider/router';
import config from 'ember-vite/config/environment';

export default class Router extends EmberRouter {
location = config.locationType;
rootURL = config.rootURL;
}

Router.map(function () {
this.route('tracing');
this.route('replay');
this.route('slow-loading-route', function () {
this.route('index', { path: '/' });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Route from '@ember/routing/route';
import * as Sentry from '@sentry/ember';

export default class ReplayRoute extends Route {
public async beforeModel(): Promise<void> {
async beforeModel(): Promise<void> {
const { replayIntegration } = Sentry;
const client = Sentry.getClient();
if (client && !client.getIntegrationByName('Replay')) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import Route from '@ember/routing/route';
import { instrumentRoutePerformance } from '@sentry/ember';

import timeout from '../helpers/utils';

const SLOW_TRANSITION_WAIT = 1500;

class SlowDefaultLoadingRoute extends Route {
public beforeModel(): Promise<void> {
beforeModel(): Promise<void> {
return timeout(SLOW_TRANSITION_WAIT / 3);
}

public model(): Promise<void> {
model(): Promise<void> {
return timeout(SLOW_TRANSITION_WAIT / 3);
}

public afterModel(): Promise<void> {
afterModel(): Promise<void> {
return timeout(SLOW_TRANSITION_WAIT / 3);
}

public setupController(...rest: Parameters<Route['setupController']>): ReturnType<Route['setupController']> {
setupController(...rest: Parameters<Route['setupController']>): ReturnType<Route['setupController']> {
super.setupController(...rest);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import Route from '@ember/routing/route';
import { instrumentRoutePerformance } from '@sentry/ember';

import timeout from '../../helpers/utils';

const SLOW_TRANSITION_WAIT = 1500;

class SlowLoadingRoute extends Route {
public beforeModel(): Promise<void> {
beforeModel(): Promise<void> {
return timeout(SLOW_TRANSITION_WAIT / 3);
}

public model(): Promise<void> {
model(): Promise<void> {
return timeout(SLOW_TRANSITION_WAIT / 3);
}

public afterModel(): Promise<void> {
afterModel(): Promise<void> {
return timeout(SLOW_TRANSITION_WAIT / 3);
}

public setupController(...rest: Parameters<Route['setupController']>): ReturnType<Route['setupController']> {
setupController(...rest: Parameters<Route['setupController']>): ReturnType<Route['setupController']> {
super.setupController(...rest);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { pageTitle } from 'ember-page-title';
import { LinkTo } from '@ember/routing';

<template>
{{pageTitle "Ember Vite"}}

<div class="app">
<h1>Sentry Ember Vite E2E Test</h1>
<nav>
<LinkTo @route="index">Errors</LinkTo>
|
<LinkTo @route="tracing">Tracing</LinkTo>
|
<LinkTo @route="replay">Replay</LinkTo>
</nav>
<main>
{{outlet}}
</main>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import TestSection from 'ember-vite/components/test-section';

function createError(): void {
const obj: Record<string, unknown> = {};
(obj as { nonExistentFunction: () => void }).nonExistentFunction();
}

function createEmberError(): void {
throw new Error('Whoops, looks like you have an EmberError');
}

function createFetchError(): void {
void fetch('http://doesntexist.example');
}

<template>
<TestSection @title="Throw Generic Javascript Error" @buttonLabel="Break Things!" @buttonFunction={{createError}} />
<TestSection @title="Throw EmberError" @buttonLabel="Break Things!" @buttonFunction={{createEmberError}} />
<TestSection @title="Error From Fetch" @buttonLabel="Break Things!" @buttonFunction={{createFetchError}} />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<h2>Visiting this page starts Replay!</h2>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<template>
<h3>Intentionally Slow Route</h3>
{{outlet}}
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<p>Slow loading route loaded.</p>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { LinkTo } from '@ember/routing';

<template>
<h2>Tracing</h2>
<LinkTo @route="slow-loading-route" data-test-button="Transition to slow loading route">
Transition to slow loading route
</LinkTo>
</template>
Loading