-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathbasebackend.ts
161 lines (143 loc) · 5.34 KB
/
basebackend.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import { Event, EventHint, Options, Session, Severity, Transport } from '@sentry/types';
import { logger, SentryError } from '@sentry/utils';
import { initAPIDetails } from './api';
import { IS_DEBUG_BUILD } from './flags';
import { createEventEnvelope, createSessionEnvelope } from './request';
import { NewTransport } from './transports/base';
import { NoopTransport } from './transports/noop';
/**
* Internal platform-dependent Sentry SDK Backend.
*
* While {@link Client} contains business logic specific to an SDK, the
* Backend offers platform specific implementations for low-level operations.
* These are persisting and loading information, sending events, and hooking
* into the environment.
*
* Backends receive a handle to the Client in their constructor. When a
* Backend automatically generates events, it must pass them to
* the Client for validation and processing first.
*
* Usually, the Client will be of corresponding type, e.g. NodeBackend
* receives NodeClient. However, higher-level SDKs can choose to instantiate
* multiple Backends and delegate tasks between them. In this case, an event
* generated by one backend might very well be sent by another one.
*
* The client also provides access to options via {@link Client.getOptions}.
* @hidden
*/
export interface Backend {
/** Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eventFromException(exception: any, hint?: EventHint): PromiseLike<Event>;
/** Creates an {@link Event} from primitive inputs to `captureMessage`. */
eventFromMessage(message: string, level?: Severity, hint?: EventHint): PromiseLike<Event>;
/** Submits the event to Sentry */
sendEvent(event: Event): void;
/** Submits the session to Sentry */
sendSession(session: Session): void;
/**
* Returns the transport that is used by the backend.
* Please note that the transport gets lazy initialized so it will only be there once the first event has been sent.
*
* @returns The transport.
*/
getTransport(): Transport;
}
/**
* A class object that can instantiate Backend objects.
* @hidden
*/
export type BackendClass<B extends Backend, O extends Options> = new (options: O) => B;
/**
* This is the base implemention of a Backend.
* @hidden
*/
export abstract class BaseBackend<O extends Options> implements Backend {
/** Options passed to the SDK. */
protected readonly _options: O;
/** Cached transport used internally. */
protected _transport: Transport;
/** New v7 Transport that is initialized alongside the old one */
protected _newTransport?: NewTransport;
/** Creates a new backend instance. */
public constructor(options: O) {
this._options = options;
if (!this._options.dsn) {
IS_DEBUG_BUILD && logger.warn('No DSN provided, backend will not do anything.');
}
this._transport = this._setupTransport();
}
/**
* @inheritDoc
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
public eventFromException(_exception: any, _hint?: EventHint): PromiseLike<Event> {
throw new SentryError('Backend has to implement `eventFromException` method');
}
/**
* @inheritDoc
*/
public eventFromMessage(_message: string, _level?: Severity, _hint?: EventHint): PromiseLike<Event> {
throw new SentryError('Backend has to implement `eventFromMessage` method');
}
/**
* @inheritDoc
*/
public sendEvent(event: Event): void {
// TODO(v7): Remove the if-else
if (
this._newTransport &&
this._options.dsn &&
this._options._experiments &&
this._options._experiments.newTransport
) {
const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel);
const env = createEventEnvelope(event, api);
void this._newTransport.send(env).then(null, reason => {
IS_DEBUG_BUILD && logger.error('Error while sending event:', reason);
});
} else {
void this._transport.sendEvent(event).then(null, reason => {
IS_DEBUG_BUILD && logger.error('Error while sending event:', reason);
});
}
}
/**
* @inheritDoc
*/
public sendSession(session: Session): void {
if (!this._transport.sendSession) {
IS_DEBUG_BUILD && logger.warn("Dropping session because custom transport doesn't implement sendSession");
return;
}
// TODO(v7): Remove the if-else
if (
this._newTransport &&
this._options.dsn &&
this._options._experiments &&
this._options._experiments.newTransport
) {
const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel);
const [env] = createSessionEnvelope(session, api);
void this._newTransport.send(env).then(null, reason => {
IS_DEBUG_BUILD && logger.error('Error while sending session:', reason);
});
} else {
void this._transport.sendSession(session).then(null, reason => {
IS_DEBUG_BUILD && logger.error('Error while sending session:', reason);
});
}
}
/**
* @inheritDoc
*/
public getTransport(): Transport {
return this._transport;
}
/**
* Sets up the transport so it can be used later to send requests.
*/
protected _setupTransport(): Transport {
return new NoopTransport();
}
}