Skip to content

Commit 56d7633

Browse files
committed
add first PoC implementation for Transport injection
1 parent 6445db2 commit 56d7633

File tree

12 files changed

+165
-16
lines changed

12 files changed

+165
-16
lines changed

packages/browser/src/client.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { BaseClient, getEnvelopeEndpointWithUrlEncodedAuth, initAPIDetails, Scope, SDK_VERSION } from '@sentry/core';
1+
import {
2+
BaseClient,
3+
getEnvelopeEndpointWithUrlEncodedAuth,
4+
initAPIDetails,
5+
NewTransport,
6+
Scope,
7+
SDK_VERSION,
8+
} from '@sentry/core';
29
import { Event, EventHint, Options, Severity, Transport, TransportOptions } from '@sentry/types';
310
import { getGlobalObject, logger, stackParserFromOptions, supportsFetch } from '@sentry/utils';
411

@@ -40,7 +47,7 @@ export class BrowserClient extends BaseClient<BrowserOptions> {
4047
*
4148
* @param options Configuration options for this SDK.
4249
*/
43-
public constructor(options: BrowserOptions = {}) {
50+
public constructor(options: BrowserOptions = {}, transport: Transport, newTransport?: NewTransport) {
4451
options._metadata = options._metadata || {};
4552
options._metadata.sdk = options._metadata.sdk || {
4653
name: 'sentry.javascript.browser',
@@ -53,7 +60,7 @@ export class BrowserClient extends BaseClient<BrowserOptions> {
5360
version: SDK_VERSION,
5461
};
5562

56-
super(options);
63+
super(options, transport, newTransport);
5764
}
5865

5966
/**

packages/browser/src/sdk.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { IS_DEBUG_BUILD } from './flags';
77
import { ReportDialogOptions, wrap as internalWrap } from './helpers';
88
import { Breadcrumbs, Dedupe, GlobalHandlers, LinkedErrors, TryCatch, UserAgent } from './integrations';
99
import { defaultStackParsers } from './stack-parsers';
10+
import { setupBrowserTransport } from './transports/setup';
1011

1112
export const defaultIntegrations = [
1213
new CoreIntegrations.InboundFilters(),
@@ -97,7 +98,8 @@ export function init(options: BrowserOptions = {}): void {
9798
options.stackParser = defaultStackParsers;
9899
}
99100

100-
initAndBind(BrowserClient, options);
101+
const { transport, newTransport } = setupBrowserTransport(options);
102+
initAndBind(BrowserClient, options, transport, newTransport);
101103

102104
if (options.autoSessionTracking) {
103105
startSessionTracking();

packages/browser/src/transports/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ export { XHRTransport } from './xhr';
44

55
export { makeNewFetchTransport } from './new-fetch';
66
export { makeNewXHRTransport } from './new-xhr';
7+
8+
export { setupBrowserTransport } from './setup';
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
BaseTransportOptions,
3+
getEnvelopeEndpointWithUrlEncodedAuth,
4+
initAPIDetails,
5+
NewTransport,
6+
NoopTransport,
7+
} from '@sentry/core';
8+
import { Transport, TransportOptions } from '@sentry/types';
9+
import { supportsFetch } from '@sentry/utils';
10+
11+
import { BrowserOptions } from '../client';
12+
import { FetchTransport } from './fetch';
13+
import { makeNewFetchTransport } from './new-fetch';
14+
import { makeNewXHRTransport } from './new-xhr';
15+
import { XHRTransport } from './xhr';
16+
17+
export interface BrowserTransportOptions extends BaseTransportOptions {
18+
// options to pass into fetch request
19+
fetchParams: Record<string, string>;
20+
headers?: Record<string, string>;
21+
sendClientReports?: boolean;
22+
}
23+
24+
/**
25+
* TODO: additional doc (since this is not part of Client anymore)
26+
* @inheritDoc
27+
*/
28+
// TODO(v7): refactor to only return newTransport
29+
export function setupBrowserTransport(options: BrowserOptions): { transport: Transport; newTransport?: NewTransport } {
30+
if (!options.dsn) {
31+
// We return the noop transport here in case there is no Dsn.
32+
return { transport: new NoopTransport() };
33+
}
34+
35+
const transportOptions: TransportOptions = {
36+
...options.transportOptions,
37+
dsn: options.dsn,
38+
tunnel: options.tunnel,
39+
sendClientReports: options.sendClientReports,
40+
_metadata: options._metadata,
41+
};
42+
43+
const api = initAPIDetails(transportOptions.dsn, transportOptions._metadata, transportOptions.tunnel);
44+
const url = getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel);
45+
46+
if (options.transport) {
47+
return { transport: new options.transport(transportOptions) };
48+
}
49+
if (supportsFetch()) {
50+
const requestOptions: RequestInit = { ...transportOptions.fetchParameters };
51+
const newTransport = makeNewFetchTransport({ requestOptions, url });
52+
const fetchTransport = new FetchTransport(transportOptions);
53+
return { transport: fetchTransport, newTransport };
54+
}
55+
56+
const newTransport = makeNewXHRTransport({
57+
url,
58+
headers: transportOptions.headers,
59+
});
60+
const transport = new XHRTransport(transportOptions);
61+
return { transport, newTransport };
62+
}

packages/core/src/baseclient.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@ export abstract class BaseClient<O extends Options> implements Client<O> {
9191
* Initializes this client instance.
9292
*
9393
* @param options Options for the client.
94+
* @param transport The (old) Transport instance for the client to use (TODO(v7): remove)
95+
* @param newTransport The NewTransport instance for the client to use
9496
*/
95-
protected constructor(options: O) {
97+
protected constructor(options: O, transport: Transport, newTransport?: NewTransport) {
9698
this._options = options;
9799

98100
if (options.dsn) {
@@ -101,7 +103,9 @@ export abstract class BaseClient<O extends Options> implements Client<O> {
101103
IS_DEBUG_BUILD && logger.warn('No DSN provided, client will not do anything.');
102104
}
103105

104-
this._transport = this._setupTransport();
106+
// TODO(v7): remove old transport
107+
this._transport = transport;
108+
this._newTransport = newTransport;
105109
}
106110

107111
/**

packages/core/src/sdk.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { getCurrentHub } from '@sentry/hub';
2-
import { Client, Options } from '@sentry/types';
2+
import { Client, Options, Transport } from '@sentry/types';
33
import { logger } from '@sentry/utils';
44

55
import { IS_DEBUG_BUILD } from './flags';
6+
import { NewTransport } from './transports/base';
67

78
/** A class object that can instantiate Client objects. */
8-
export type ClientClass<F extends Client, O extends Options> = new (options: O) => F;
9+
export type ClientClass<F extends Client, O extends Options> = new (
10+
options: O,
11+
transport: Transport,
12+
newTransport?: NewTransport,
13+
) => F;
914

1015
/**
1116
* Internal function to create a new SDK client instance. The client is
@@ -14,7 +19,12 @@ export type ClientClass<F extends Client, O extends Options> = new (options: O)
1419
* @param clientClass The client class to instantiate.
1520
* @param options Options to pass to the client.
1621
*/
17-
export function initAndBind<F extends Client, O extends Options>(clientClass: ClientClass<F, O>, options: O): void {
22+
export function initAndBind<F extends Client, O extends Options>(
23+
clientClass: ClientClass<F, O>,
24+
options: O,
25+
transport: Transport,
26+
newTransport?: NewTransport,
27+
): void {
1828
if (options.debug === true) {
1929
if (IS_DEBUG_BUILD) {
2030
logger.enable();
@@ -29,6 +39,7 @@ export function initAndBind<F extends Client, O extends Options>(clientClass: Cl
2939
if (scope) {
3040
scope.update(options.initialScope);
3141
}
32-
const client = new clientClass(options);
42+
43+
const client = new clientClass(options, transport, newTransport);
3344
hub.bindClient(client);
3445
}

packages/core/src/transports/base.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,14 @@ export type TransportResponse = {
5151
interface InternalBaseTransportOptions {
5252
bufferSize?: number;
5353
}
54-
5554
export interface BaseTransportOptions extends InternalBaseTransportOptions {
5655
// url to send the event
5756
// transport does not care about dsn specific - client should take care of
5857
// parsing and figuring that out
5958
url: string;
6059
}
6160

62-
// TODO: Move into Browser Transport
61+
// TODO(v7): Delete
6362
export interface BrowserTransportOptions extends BaseTransportOptions {
6463
// options to pass into fetch request
6564
fetchParams: Record<string, string>;

packages/core/test/mocks/client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export class TestClient extends BaseClient<TestOptions> {
7474
}
7575
}
7676

77+
// TODO(v7): wtf?
7778
export function init(options: TestOptions): void {
7879
initAndBind(TestClient, options);
7980
}

packages/node/src/client.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { BaseClient, getEnvelopeEndpointWithUrlEncodedAuth, initAPIDetails, Scope, SDK_VERSION } from '@sentry/core';
1+
import {
2+
BaseClient,
3+
getEnvelopeEndpointWithUrlEncodedAuth,
4+
initAPIDetails,
5+
NewTransport,
6+
Scope,
7+
SDK_VERSION,
8+
} from '@sentry/core';
29
import { SessionFlusher } from '@sentry/hub';
310
import { Event, EventHint, Severity, Transport, TransportOptions } from '@sentry/types';
411
import { logger, makeDsn, resolvedSyncPromise, stackParserFromOptions } from '@sentry/utils';
@@ -21,7 +28,7 @@ export class NodeClient extends BaseClient<NodeOptions> {
2128
* Creates a new Node SDK instance.
2229
* @param options Configuration options for this SDK.
2330
*/
24-
public constructor(options: NodeOptions) {
31+
public constructor(options: NodeOptions, transport: Transport, newTransport?: NewTransport) {
2532
options._metadata = options._metadata || {};
2633
options._metadata.sdk = options._metadata.sdk || {
2734
name: 'sentry.javascript.node',
@@ -34,7 +41,7 @@ export class NodeClient extends BaseClient<NodeOptions> {
3441
version: SDK_VERSION,
3542
};
3643

37-
super(options);
44+
super(options, transport, newTransport);
3845
}
3946

4047
/**
@@ -149,6 +156,7 @@ export class NodeClient extends BaseClient<NodeOptions> {
149156

150157
/**
151158
* @inheritDoc
159+
* TODO(v7): delete
152160
*/
153161
protected _setupTransport(): Transport {
154162
if (!this._options.dsn) {

packages/node/src/sdk.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { NodeClient } from './client';
88
import { IS_DEBUG_BUILD } from './flags';
99
import { Console, ContextLines, Http, LinkedErrors, OnUncaughtException, OnUnhandledRejection } from './integrations';
1010
import { nodeStackParser } from './stack-parser';
11+
import { setupNodeTransport } from './transports';
1112
import { NodeOptions } from './types';
1213

1314
export const defaultIntegrations = [
@@ -130,7 +131,9 @@ export function init(options: NodeOptions = {}): void {
130131
setHubOnCarrier(carrier, getCurrentHub());
131132
}
132133

133-
initAndBind(NodeClient, options);
134+
// TODO(v7): Init transport here and pass it to initAndBind
135+
const { transport, newTransport } = setupNodeTransport(options);
136+
initAndBind(NodeClient, options, transport, newTransport);
134137

135138
if (options.autoSessionTracking) {
136139
startSessionTracking();

packages/node/src/transports/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export { BaseTransport } from './base';
22
export { HTTPTransport } from './http';
33
export { HTTPSTransport } from './https';
44
export { makeNodeTransport, NodeTransportOptions } from './new';
5+
export { setupNodeTransport } from './setup';

packages/node/src/transports/setup.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { getEnvelopeEndpointWithUrlEncodedAuth, initAPIDetails, NewTransport, NoopTransport } from '@sentry/core';
2+
import { Transport, TransportOptions } from '@sentry/types';
3+
import { makeDsn } from '@sentry/utils';
4+
5+
import { NodeOptions } from '../types';
6+
import { HTTPSTransport, HTTPTransport, makeNodeTransport } from '.';
7+
8+
/**
9+
* TODO(v7): Add documentation
10+
* @inheritDoc
11+
*/
12+
// TODO(v7): Adjust when NewTransport is the default
13+
export function setupNodeTransport(options: NodeOptions): { transport: Transport; newTransport?: NewTransport } {
14+
if (!options.dsn) {
15+
// We return the noop transport here in case there is no Dsn.
16+
return { transport: new NoopTransport() };
17+
}
18+
19+
const dsn = makeDsn(options.dsn);
20+
21+
const transportOptions: TransportOptions = {
22+
...options.transportOptions,
23+
...(options.httpProxy && { httpProxy: options.httpProxy }),
24+
...(options.httpsProxy && { httpsProxy: options.httpsProxy }),
25+
...(options.caCerts && { caCerts: options.caCerts }),
26+
dsn: options.dsn,
27+
tunnel: options.tunnel,
28+
_metadata: options._metadata,
29+
};
30+
31+
if (options.transport) {
32+
return { transport: new options.transport(transportOptions) };
33+
}
34+
35+
const api = initAPIDetails(transportOptions.dsn, transportOptions._metadata, transportOptions.tunnel);
36+
const url = getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel);
37+
38+
const newTransport = makeNodeTransport({
39+
url,
40+
headers: transportOptions.headers,
41+
proxy: transportOptions.httpProxy,
42+
caCerts: transportOptions.caCerts,
43+
});
44+
45+
if (dsn.protocol === 'http') {
46+
return { transport: new HTTPTransport(transportOptions), newTransport };
47+
}
48+
return { transport: new HTTPSTransport(transportOptions), newTransport };
49+
}

0 commit comments

Comments
 (0)