Skip to content

[NEXT] Frontend -> Client #1323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 11, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 2 additions & 2 deletions packages/browser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ If you don't want to use a global static instance of Sentry, you can create one
yourself:

```javascript
import { BrowserFrontend } from '@sentry/browser';
import { BrowserClient } from '@sentry/browser';

const client = new BrowserFrontend({
const client = new BrowserClient({
dsn: '__DSN__',
// ...
});
Expand Down
26 changes: 14 additions & 12 deletions packages/browser/src/backend.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Backend, Frontend, Options, SentryError } from '@sentry/core';
import { Backend, Client, Options, SentryError } from '@sentry/core';
import {
addBreadcrumb,
captureEvent,
Expand All @@ -12,7 +12,9 @@ const sendRavenEvent = Raven._sendProcessedPayload.bind(Raven) as SendMethod;

/** Normalizes the event so it is consistent with our domain interface. */
function normalizeRavenEvent(event: SentryEvent): SentryEvent {
const ex = (event.exception || {}) as { values?: SentryException[] };
const ex = ((event && event.exception) || {}) as {
Copy link
Member Author

@HazAT HazAT May 9, 2018

Choose a reason for hiding this comment

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

There was an issue when running it with SDK loader thatevent was null/undefined.

Copy link
Member

Choose a reason for hiding this comment

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

That's not to be solved here.

Copy link
Member

Choose a reason for hiding this comment

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

Can we fix this in captureEvent and change the top-level signature to SentryEvent | undefined? This is way too deep and also defies type checking.

values?: SentryException[];
};
if (ex && ex.values) {
event.exception = ex.values;
}
Expand All @@ -32,7 +34,7 @@ function prepareEventForRaven(event: SentryEvent): SentryEvent {

/**
* Configuration options for the Sentry Browser SDK.
* @see BrowserFrontend for more information.
* @see BrowserClient for more information.
*/
export interface BrowserOptions extends Options {
/**
Expand Down Expand Up @@ -65,40 +67,40 @@ export interface BrowserOptions extends Options {

/** The Sentry Browser SDK Backend. */
export class BrowserBackend implements Backend {
/** Handle to the SDK frontend for callbacks. */
private readonly frontend: Frontend<BrowserOptions>;
/** Handle to the SDK client for callbacks. */
private readonly client: Client<BrowserOptions>;

/** Creates a new browser backend instance. */
public constructor(frontend: Frontend<BrowserOptions>) {
this.frontend = frontend;
public constructor(client: Client<BrowserOptions>) {
this.client = client;
}

/**
* @inheritDoc
*/
public install(): boolean {
// We are only called by the frontend if the SDK is enabled and a valid DSN
// We are only called by the client if the SDK is enabled and a valid DSN
// has been configured. If no DSN is present, this indicates a programming
// error.
const dsn = this.frontend.getDSN();
const dsn = this.client.getDSN();
if (!dsn) {
throw new SentryError(
'Invariant exception: install() must not be called when disabled',
);
}

Raven.config(dsn.toString(), this.frontend.getOptions()).install();
Raven.config(dsn.toString(), this.client.getOptions()).install();

// Hook into Raven's breadcrumb mechanism. This allows us to intercept both
// breadcrumbs created internally by Raven and pass them to the Frontend
// breadcrumbs created internally by Raven and pass them to the Client
// first, before actually capturing them.
Raven.setBreadcrumbCallback(breadcrumb => {
addBreadcrumb(breadcrumb);
return false;
});

// Hook into Raven's internal event sending mechanism. This allows us to
// pass events to the frontend, before they will be sent back here for
// pass events to the client, before they will be sent back here for
// actual submission.
Raven._sendProcessedPayload = event => {
captureEvent(normalizeRavenEvent(event));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { FrontendBase } from '@sentry/core';
import { ClientBase } from '@sentry/core';
import { SdkInfo } from '@sentry/shim';
import { BrowserBackend, BrowserOptions } from './backend';
import { Raven } from './raven';

/**
* The Sentry Browser SDK Frontend.
* The Sentry Browser SDK Client.
*
* @see BrowserOptions for documentation on configuration options.
* @see SentryClient for usage documentation.
*/
export class BrowserFrontend extends FrontendBase<
BrowserBackend,
BrowserOptions
> {
export class BrowserClient extends ClientBase<BrowserBackend, BrowserOptions> {
/**
* Creates a new Browser SDK instance.
*
Expand Down
4 changes: 2 additions & 2 deletions packages/browser/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ export {
} from '@sentry/shim';

export { BrowserBackend, BrowserOptions } from './backend';
export { BrowserFrontend } from './frontend';
export { init, getCurrentFrontend } from './sdk';
export { BrowserClient } from './client';
export { init, getCurrentClient } from './sdk';
12 changes: 6 additions & 6 deletions packages/browser/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { initAndBind } from '@sentry/core';
import { getCurrentClient } from '@sentry/shim';
import { getCurrentClient as shimGetCurrentClient } from '@sentry/shim';
import { BrowserOptions } from './backend';
import { BrowserFrontend } from './frontend';
import { BrowserClient } from './client';

/**
* The Sentry Browser SDK Client.
Expand Down Expand Up @@ -47,10 +47,10 @@ import { BrowserFrontend } from './frontend';
* @see BrowserOptions for documentation on configuration options.
*/
export function init(options: BrowserOptions): void {
initAndBind(BrowserFrontend, options);
initAndBind(BrowserClient, options);
}

/** Returns the current BrowserFrontend, if any. */
export function getCurrentFrontend(): BrowserFrontend {
return getCurrentClient() as BrowserFrontend;
/** Returns the current BrowserClient, if any. */
export function getCurrentClient(): BrowserClient {
return shimGetCurrentClient() as BrowserClient;
}
12 changes: 6 additions & 6 deletions packages/browser/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { spy, stub } from 'sinon';
import {
addBreadcrumb,
BrowserBackend,
BrowserFrontend,
BrowserClient,
captureEvent,
captureException,
captureMessage,
Expand All @@ -29,7 +29,7 @@ describe('SentryBrowser', () => {
let s: sinon.SinonSpy;

beforeEach(() => {
s = spy(BrowserFrontend.prototype, 'setContext');
s = spy(BrowserClient.prototype, 'setContext');
});

afterEach(() => {
Expand Down Expand Up @@ -70,7 +70,7 @@ describe('SentryBrowser', () => {

it('should record auto breadcrumbs', done => {
pushScope(
new BrowserFrontend({
new BrowserClient({
afterSend: (event: SentryEvent) => {
expect(event.breadcrumbs!).to.have.lengthOf(3);
done();
Expand Down Expand Up @@ -110,7 +110,7 @@ describe('SentryBrowser', () => {

it('should capture an exception', done => {
pushScope(
new BrowserFrontend({
new BrowserClient({
afterSend: (event: SentryEvent) => {
expect(event.exception).to.not.be.undefined;
expect(event.exception![0]).to.not.be.undefined;
Expand All @@ -132,7 +132,7 @@ describe('SentryBrowser', () => {

it('should capture a message', done => {
pushScope(
new BrowserFrontend({
new BrowserClient({
afterSend: (event: SentryEvent) => {
expect(event.message).to.equal('test');
expect(event.exception).to.be.undefined;
Expand All @@ -147,7 +147,7 @@ describe('SentryBrowser', () => {

it('should capture an event', done => {
pushScope(
new BrowserFrontend({
new BrowserClient({
afterSend: (event: SentryEvent) => {
expect(event.message).to.equal('test');
expect(event.exception).to.be.undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ building Sentry JavaScript SDKs, like `@sentry/node` or `@sentry/browser`.

TODO

## Specializing the Frontend
## Specializing the Client

TODO

Expand Down
36 changes: 18 additions & 18 deletions packages/core/src/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Breadcrumb, Context, SdkInfo, SentryEvent } from '@sentry/shim';
import { DSN } from './dsn';
import { Backend, Frontend, Options, Scope } from './interfaces';
import { Backend, Client, Options, Scope } from './interfaces';
import { SendStatus } from './status';

/**
Expand All @@ -17,49 +17,49 @@ const MAX_BREADCRUMBS = 100;

/** A class object that can instanciate Backend objects. */
export interface BackendClass<B extends Backend, O extends Options> {
new (frontend: Frontend<O>): B;
new (client: Client<O>): B;
}

/**
* Base implementation for all JavaScript SDK frontends.
* Base implementation for all JavaScript SDK clients.
*
* Call the constructor with the corresponding backend constructor and options
* specific to the frontend subclass. To access these options later, use
* {@link Frontend.getOptions}. Also, the Backend instance is available via
* {@link Frontend.getBackend}.
* specific to the client subclass. To access these options later, use
* {@link Client.getOptions}. Also, the Backend instance is available via
* {@link Client.getBackend}.
*
* Subclasses must implement one abstract method: {@link getSdkInfo}. It must
* return the unique name and the version of the SDK.
*
* If a DSN is specified in the options, it will be parsed and stored. Use
* {@link Frontend.getDSN} to retrieve the DSN at any moment. In case the DSN is
* {@link Client.getDSN} to retrieve the DSN at any moment. In case the DSN is
* invalid, the constructor will throw a {@link SentryException}. Note that
* without a valid DSN, the SDK will not send any events to Sentry.
*
* Before sending an event via the backend, it is passed through
* {@link FrontendBase.prepareEvent} to add SDK information and scope data
* {@link ClientBase.prepareEvent} to add SDK information and scope data
* (breadcrumbs and context). To add more custom information, override this
* method and extend the resulting prepared event.
*
* To issue automatically created events (e.g. via instrumentation), use
* {@link Frontend.captureEvent}. It will prepare the event and pass it through
* {@link Client.captureEvent}. It will prepare the event and pass it through
* the callback lifecycle. To issue auto-breadcrumbs, use
* {@link Frontend.addBreadcrumb}.
* {@link Client.addBreadcrumb}.
*
* @example
* class NodeFrontend extends FrontendBase<NodeBackend, NodeOptions> {
* class NodeClient extends ClientBase<NodeBackend, NodeOptions> {
* public constructor(options: NodeOptions) {
* super(NodeBackend, options);
* }
*
* // ...
* }
*/
export abstract class FrontendBase<B extends Backend, O extends Options>
implements Frontend<O> {
export abstract class ClientBase<B extends Backend, O extends Options>
implements Client<O> {
/**
* The backend used to physically interact in the enviornment. Usually, this
* will correspond to the frontend. When composing SDKs, however, the Backend
* will correspond to the client. When composing SDKs, however, the Backend
* from the root SDK will be used.
*/
private readonly backend: B;
Expand All @@ -76,7 +76,7 @@ export abstract class FrontendBase<B extends Backend, O extends Options>
/**
* A scope instance containing breadcrumbs and context, used if none is
* specified to the public methods. This is specifically used in standalone
* mode, when the Frontend is directly instanciated by the user.
* mode, when the Client is directly instanciated by the user.
*/
private readonly internalScope: Scope;

Expand All @@ -87,10 +87,10 @@ export abstract class FrontendBase<B extends Backend, O extends Options>
private installed?: boolean;

/**
* Initializes this frontend instance.
* Initializes this client instance.
*
* @param backendClass A constructor function to create the backend.
* @param options Options for the frontend.
* @param options Options for the client.
*/
protected constructor(backendClass: BackendClass<B, O>, options: O) {
this.backend = new backendClass(this);
Expand Down Expand Up @@ -259,7 +259,7 @@ export abstract class FrontendBase<B extends Backend, O extends Options>
* Adds common information to events.
*
* The information includes release and environment from `options`, SDK
* information returned by {@link FrontendBase.getSdkInfo}, as well as
* information returned by {@link ClientBase.getSdkInfo}, as well as
* breadcrumbs and context (extra, tags and user) from the scope.
*
* Information that is already present in the event is never overwritten. For
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { BackendClass, FrontendBase } from './base';
export { BackendClass, ClientBase } from './base';
export { DSN, DSNComponents, DSNLike, DSNProtocol } from './dsn';
export { SentryError } from './error';
export { Backend, Frontend, LogLevel, Options, Scope } from './interfaces';
export { initAndBind, FrontendClass } from './sdk';
export { Backend, Client, LogLevel, Options, Scope } from './interfaces';
export { initAndBind, ClientClass } from './sdk';
Loading