Skip to content

Commit 01be670

Browse files
committed
feat: Expose sdkinfo, Add auth header
1 parent f6fd30b commit 01be670

File tree

11 files changed

+102
-90
lines changed

11 files changed

+102
-90
lines changed

packages/browser/src/backend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { FetchTransport, XHRTransport } from './transports';
77

88
/**
99
* Configuration options for the Sentry Browser SDK.
10-
* @see BrowserClient for more information.
10+
* @see BrowserClient afor more information.
1111
*/
1212
export interface BrowserOptions extends Options {
1313
/**

packages/browser/src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class BrowserClient extends BaseClient<BrowserBackend, BrowserOptions> {
2222
/**
2323
* @inheritDoc
2424
*/
25-
protected getSdkInfo(): SdkInfo {
25+
public getSdkInfo(): SdkInfo {
2626
return {
2727
name: 'sentry-browser',
2828
version: Raven.VERSION,

packages/core/src/base.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,10 @@ export abstract class BaseClient<B extends Backend, O extends Options>
206206
return this.options;
207207
}
208208

209-
/** Returns the current used SDK version and name. */
210-
protected abstract getSdkInfo(): SdkInfo;
209+
/**
210+
* @inheritDoc
211+
*/
212+
public abstract getSdkInfo(): SdkInfo;
211213

212214
/** Returns the current backend. */
213215
protected getBackend(): B {

packages/core/src/interfaces.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Scope } from '@sentry/hub';
22
import {
33
Breadcrumb,
44
Integration,
5+
SdkInfo,
56
SentryEvent,
67
SentryResponse,
78
Transport,
@@ -210,6 +211,9 @@ export interface Client<O extends Options = Options> {
210211

211212
/** Returns the current options. */
212213
getOptions(): O;
214+
215+
/** Returns the current used SDK version and name. */
216+
getSdkInfo(): SdkInfo;
213217
}
214218

215219
/**

packages/node/src/backend.ts

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import { Backend, DSN, Options, SentryError } from '@sentry/core';
22
import { addBreadcrumb, captureEvent } from '@sentry/minimal';
3-
import { SentryEvent } from '@sentry/types';
4-
import {
5-
HTTPSTransport,
6-
HTTPTransport,
7-
Raven,
8-
SendMethod,
9-
Transport,
10-
} from './raven';
11-
12-
/** Original Raven send function. */
13-
const sendRavenEvent = Raven.send.bind(Raven) as SendMethod;
3+
import { SentryEvent, SentryResponse } from '@sentry/types';
4+
import { Raven } from './raven';
5+
import { HTTPSTransport, HTTPTransport } from './transports';
146

157
/** Extension to the Function type. */
168
interface FunctionExt extends Function {
179
__SENTRY_CAPTURE__?: boolean;
1810
}
1911

12+
/** Prepares an event so it can be send with raven-js. */
13+
function normalizeEvent(ravenEvent: any): SentryEvent {
14+
const event = ravenEvent;
15+
// tslint:disable-next-line:no-unsafe-any
16+
if (ravenEvent.exception && !ravenEvent.exception.values) {
17+
// tslint:disable-next-line:no-unsafe-any
18+
event.exception = { values: ravenEvent.exception };
19+
}
20+
return event as SentryEvent;
21+
}
22+
2023
/**
2124
* Configuration options for the Sentry Node SDK.
2225
* @see NodeClient for more information.
@@ -85,9 +88,9 @@ export class NodeBackend implements Backend {
8588
// actual submission.
8689
Raven.send = (event, callback) => {
8790
if (callback && (callback as FunctionExt).__SENTRY_CAPTURE__) {
88-
callback(event);
91+
callback(normalizeEvent(event));
8992
} else {
90-
captureEvent(event);
93+
captureEvent(normalizeEvent(event));
9194
// TODO: Check if this is fine
9295
if (callback) {
9396
callback(event);
@@ -121,13 +124,22 @@ export class NodeBackend implements Backend {
121124
/**
122125
* @inheritDoc
123126
*/
124-
public async sendEvent(event: SentryEvent): Promise<number> {
125-
return new Promise<number>(resolve => {
126-
sendRavenEvent(event, error => {
127-
// TODO: Check the response status code
128-
resolve(error ? 500 : 200);
129-
});
130-
});
127+
public async sendEvent(event: SentryEvent): Promise<SentryResponse> {
128+
let dsn: DSN;
129+
130+
if (!this.options.dsn) {
131+
throw new SentryError('Cannot sendEvent without a valid DSN');
132+
} else {
133+
dsn = new DSN(this.options.dsn);
134+
}
135+
136+
const transport = this.options.transport
137+
? new this.options.transport({ dsn })
138+
: dsn.protocol === 'http'
139+
? new HTTPTransport({ dsn })
140+
: new HTTPSTransport({ dsn });
141+
142+
return transport.send(event);
131143
}
132144

133145
/**
@@ -143,25 +155,4 @@ export class NodeBackend implements Backend {
143155
public storeScope(): void {
144156
// Noop
145157
}
146-
147-
/**
148-
* Set the transport module used for submitting events.
149-
*
150-
* This can be set to modules like "http" or "https" or any other object that
151-
* provides a `request` method with options.
152-
*
153-
* @param transport The transport to use for submitting events.
154-
*/
155-
public setTransport(transport: Transport): void {
156-
const dsn = this.options.dsn;
157-
if (!dsn) {
158-
return;
159-
}
160-
const dsnObject = new DSN(dsn);
161-
162-
Raven.transport =
163-
dsnObject.protocol === 'http'
164-
? new HTTPTransport({ transport })
165-
: new HTTPSTransport({ transport });
166-
}
167158
}

packages/node/src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class NodeClient extends BaseClient<NodeBackend, NodeOptions> {
2121
/**
2222
* @inheritDoc
2323
*/
24-
protected getSdkInfo(): SdkInfo {
24+
public getSdkInfo(): SdkInfo {
2525
return {
2626
name: 'sentry-node',
2727
version: Raven.version,

packages/node/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ export {
44
SdkInfo,
55
SentryEvent,
66
SentryException,
7+
SentryResponse,
78
Severity,
89
StackFrame,
910
Stacktrace,
11+
Status,
1012
Thread,
1113
User,
1214
} from '@sentry/types';
@@ -28,3 +30,6 @@ export { init } from './sdk';
2830

2931
import * as Integrations from './integrations';
3032
export { Integrations };
33+
34+
import * as Transports from './transports';
35+
export { Transports };

packages/node/src/raven.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,6 @@ import * as RavenNode from 'raven';
33

44
export type SendMethod = (event: SentryEvent, cb?: (err: any) => void) => void;
55

6-
/** A HTTP transport module. */
7-
export interface Transport {
8-
request(options: object | string): void;
9-
}
10-
11-
/** A Raven transport wrapper. */
12-
export interface RavenTransport {
13-
send(): void;
14-
}
15-
16-
/** A constructor class that creates a RavenTransport. */
17-
export interface TransportClass {
18-
new (options: { transport: Transport }): RavenTransport;
19-
}
20-
216
/** Provides access to internal raven functionality. */
227
export interface RavenInternal {
238
captureBreadcrumb(breadcrumb: Breadcrumb): void;
@@ -26,7 +11,6 @@ export interface RavenInternal {
2611
config(dsn: string, options: object): RavenInternal;
2712
install(onFatalError?: (error: Error) => void): void;
2813
send: SendMethod;
29-
transport: RavenTransport;
3014
version: string;
3115
// TODO: Remove once integrations are ported
3216
onFatalError(error: Error): void;
@@ -37,12 +21,3 @@ export interface RavenInternal {
3721
/** Casted raven instance with access to internal functions. */
3822
// tslint:disable-next-line:variable-name
3923
export const Raven: RavenInternal = RavenNode as any;
40-
41-
/** Interface for transports exported by RavenNode. */
42-
interface Transports {
43-
HTTPSTransport: TransportClass;
44-
HTTPTransport: TransportClass;
45-
}
46-
47-
export const { HTTPSTransport, HTTPTransport } = (RavenNode as any)
48-
.transports as Transports;

packages/node/src/transports/base.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import { DSN, SentryError } from '@sentry/core';
22
import {
33
SentryEvent,
44
SentryResponse,
5+
Status,
56
Transport,
67
TransportOptions as BaseOptions,
78
} from '@sentry/types';
89
import { serialize } from '@sentry/utils/src/object';
910
import * as http from 'http';
1011
import * as https from 'https';
12+
import { getDefaultHub, NodeClient } from '../index';
1113

1214
/** TODO */
1315
export interface HTTPRequest {
@@ -41,13 +43,37 @@ export abstract class BaseTransport implements Transport {
4143
this.dsn = new DSN(options.dsn);
4244
}
4345

46+
/** TODO */
47+
private getAuthHeader(): string {
48+
const header = ['Sentry sentry_version=7'];
49+
header.push(`sentry_timestamp=${new Date().getTime()}`);
50+
const client = getDefaultHub().getClient() as NodeClient;
51+
if (client) {
52+
header.push(
53+
`sentry_client=${client.getSdkInfo().name}/${
54+
client.getSdkInfo().version
55+
}`,
56+
);
57+
}
58+
header.push(`sentry_key=${this.dsn.user}`);
59+
if (this.dsn.pass) {
60+
header.push(`sentry_secret=${this.dsn.pass}`);
61+
}
62+
return header.join(', ');
63+
}
64+
4465
/**
4566
* TODO
4667
*/
4768
protected getRequestOptions(): http.RequestOptions {
69+
const headers = {
70+
'X-Sentry-Auth': this.getAuthHeader(),
71+
...this.options.headers,
72+
};
73+
4874
return {
4975
agent: this.client,
50-
headers: this.options.headers,
76+
headers,
5177
hostname: this.dsn.host,
5278
method: 'POST',
5379
path: `${this.dsn.path}/api/${this.dsn.projectId}/store/`,
@@ -68,8 +94,9 @@ export abstract class BaseTransport implements Transport {
6894
res.setEncoding('utf8');
6995
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
7096
resolve({
97+
code: res.statusCode,
7198
event_id: event.event_id,
72-
status: res.statusCode,
99+
status: Status.fromHttpCode(res.statusCode),
73100
});
74101
} else {
75102
const reason = res.headers['x-sentry-error'];

packages/node/test/index.test.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
import * as domain from 'domain';
22
import * as RavenNode from 'raven';
33

4-
// -----------------------------------------------------------------------------
5-
// It's important that we stub this before we import the backend
6-
jest
7-
.spyOn(RavenNode as any, 'send')
8-
.mockImplementation((_: SentryEvent, cb: () => void) => {
9-
cb();
10-
});
11-
// -----------------------------------------------------------------------------
12-
134
import {
145
addBreadcrumb,
156
captureEvent,
@@ -22,6 +13,7 @@ import {
2213
NodeClient,
2314
Scope,
2415
SentryEvent,
16+
SentryResponse,
2517
} from '../src';
2618

2719
const dsn = 'https://[email protected]/4291';
@@ -71,12 +63,12 @@ describe('SentryNode', () => {
7163
});
7264

7365
describe('breadcrumbs', () => {
74-
let s: jest.Mock<(event: SentryEvent) => Promise<number>>;
66+
let s: jest.Mock<(event: SentryEvent) => Promise<SentryResponse>>;
7567

7668
beforeEach(() => {
7769
s = jest
7870
.spyOn(NodeBackend.prototype, 'sendEvent')
79-
.mockImplementation(async () => Promise.resolve(200));
71+
.mockImplementation(async () => Promise.resolve({ code: 200 }));
8072
});
8173

8274
afterEach(() => {
@@ -111,12 +103,12 @@ describe('SentryNode', () => {
111103
});
112104

113105
describe('capture', () => {
114-
let s: jest.Mock<(event: SentryEvent) => Promise<number>>;
106+
let s: jest.Mock<(event: SentryEvent) => Promise<SentryResponse>>;
115107

116108
beforeEach(() => {
117109
s = jest
118110
.spyOn(NodeBackend.prototype, 'sendEvent')
119-
.mockImplementation(async () => Promise.resolve(200));
111+
.mockImplementation(async () => Promise.resolve({ code: 200 }));
120112
});
121113

122114
afterEach(() => {
@@ -130,10 +122,10 @@ describe('SentryNode', () => {
130122
afterSend: (event: SentryEvent) => {
131123
expect(event.tags).toEqual({ test: '1' });
132124
expect(event.exception).not.toBeUndefined();
133-
expect(event.exception![0]).not.toBeUndefined();
134-
expect(event.exception![0].type).toBe('Error');
135-
expect(event.exception![0].value).toBe('test');
136-
expect(event.exception![0].stacktrace).toBeTruthy();
125+
expect(event.exception!.values[0]).not.toBeUndefined();
126+
expect(event.exception!.values[0].type).toBe('Error');
127+
expect(event.exception!.values[0].value).toBe('test');
128+
expect(event.exception!.values[0].stacktrace).toBeTruthy();
137129
done();
138130
},
139131
dsn,

packages/node/test/transports.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { captureException, init, SentryEvent } from '../src';
2+
3+
const dsn = 'https://[email protected]/50622';
4+
5+
describe('HTTPTransport', () => {
6+
test('captureEvent', done => {
7+
init({
8+
afterSend: (event: SentryEvent) => {
9+
expect(event.message).toBe('test');
10+
done();
11+
},
12+
dsn,
13+
});
14+
captureException(new Error('wat'));
15+
});
16+
});

0 commit comments

Comments
 (0)