package.build.esm.server-runtime-client.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core Show documentation
Show all versions of core Show documentation
Base implementation for all Sentry JavaScript SDKs
import { resolvedSyncPromise, eventFromUnknownInput, eventFromMessage, logger, uuid4 } from '@sentry/utils';
import { BaseClient } from './baseclient.js';
import { createCheckInEnvelope } from './checkin.js';
import { getIsolationScope } from './currentScopes.js';
import { DEBUG_BUILD } from './debug-build.js';
import { SessionFlusher } from './sessionflusher.js';
import { registerSpanErrorInstrumentation } from './tracing/errors.js';
import { _getSpanForScope } from './utils/spanOnScope.js';
import { getRootSpan, spanToTraceContext } from './utils/spanUtils.js';
import { getDynamicSamplingContextFromSpan, getDynamicSamplingContextFromClient } from './tracing/dynamicSamplingContext.js';
/**
* The Sentry Server Runtime Client SDK.
*/
class ServerRuntimeClient
extends BaseClient {
/**
* Creates a new Edge SDK instance.
* @param options Configuration options for this SDK.
*/
constructor(options) {
// Server clients always support tracing
registerSpanErrorInstrumentation();
super(options);
}
/**
* @inheritDoc
*/
eventFromException(exception, hint) {
return resolvedSyncPromise(eventFromUnknownInput(this, this._options.stackParser, exception, hint));
}
/**
* @inheritDoc
*/
eventFromMessage(
message,
level = 'info',
hint,
) {
return resolvedSyncPromise(
eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace),
);
}
/**
* @inheritDoc
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
captureException(exception, hint, scope) {
// Check if the flag `autoSessionTracking` is enabled, and if `_sessionFlusher` exists because it is initialised only
// when the `requestHandler` middleware is used, and hence the expectation is to have SessionAggregates payload
// sent to the Server only when the `requestHandler` middleware is used
if (this._options.autoSessionTracking && this._sessionFlusher) {
const requestSession = getIsolationScope().getRequestSession();
// Necessary checks to ensure this is code block is executed only within a request
// Should override the status only if `requestSession.status` is `Ok`, which is its initial stage
if (requestSession && requestSession.status === 'ok') {
requestSession.status = 'errored';
}
}
return super.captureException(exception, hint, scope);
}
/**
* @inheritDoc
*/
captureEvent(event, hint, scope) {
// Check if the flag `autoSessionTracking` is enabled, and if `_sessionFlusher` exists because it is initialised only
// when the `requestHandler` middleware is used, and hence the expectation is to have SessionAggregates payload
// sent to the Server only when the `requestHandler` middleware is used
if (this._options.autoSessionTracking && this._sessionFlusher) {
const eventType = event.type || 'exception';
const isException =
eventType === 'exception' && event.exception && event.exception.values && event.exception.values.length > 0;
// If the event is of type Exception, then a request session should be captured
if (isException) {
const requestSession = getIsolationScope().getRequestSession();
// Ensure that this is happening within the bounds of a request, and make sure not to override
// Session Status if Errored / Crashed
if (requestSession && requestSession.status === 'ok') {
requestSession.status = 'errored';
}
}
}
return super.captureEvent(event, hint, scope);
}
/**
*
* @inheritdoc
*/
close(timeout) {
if (this._sessionFlusher) {
this._sessionFlusher.close();
}
return super.close(timeout);
}
/** Method that initialises an instance of SessionFlusher on Client */
initSessionFlusher() {
const { release, environment } = this._options;
if (!release) {
DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!');
} else {
this._sessionFlusher = new SessionFlusher(this, {
release,
environment,
});
}
}
/**
* Create a cron monitor check in and send it to Sentry.
*
* @param checkIn An object that describes a check in.
* @param upsertMonitorConfig An optional object that describes a monitor config. Use this if you want
* to create a monitor automatically when sending a check in.
*/
captureCheckIn(checkIn, monitorConfig, scope) {
const id = 'checkInId' in checkIn && checkIn.checkInId ? checkIn.checkInId : uuid4();
if (!this._isEnabled()) {
DEBUG_BUILD && logger.warn('SDK not enabled, will not capture checkin.');
return id;
}
const options = this.getOptions();
const { release, environment, tunnel } = options;
const serializedCheckIn = {
check_in_id: id,
monitor_slug: checkIn.monitorSlug,
status: checkIn.status,
release,
environment,
};
if ('duration' in checkIn) {
serializedCheckIn.duration = checkIn.duration;
}
if (monitorConfig) {
serializedCheckIn.monitor_config = {
schedule: monitorConfig.schedule,
checkin_margin: monitorConfig.checkinMargin,
max_runtime: monitorConfig.maxRuntime,
timezone: monitorConfig.timezone,
failure_issue_threshold: monitorConfig.failureIssueThreshold,
recovery_threshold: monitorConfig.recoveryThreshold,
};
}
const [dynamicSamplingContext, traceContext] = this._getTraceInfoFromScope(scope);
if (traceContext) {
serializedCheckIn.contexts = {
trace: traceContext,
};
}
const envelope = createCheckInEnvelope(
serializedCheckIn,
dynamicSamplingContext,
this.getSdkMetadata(),
tunnel,
this.getDsn(),
);
DEBUG_BUILD && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status);
// sendEnvelope should not throw
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.sendEnvelope(envelope);
return id;
}
/**
* Method responsible for capturing/ending a request session by calling `incrementSessionStatusCount` to increment
* appropriate session aggregates bucket
*/
_captureRequestSession() {
if (!this._sessionFlusher) {
DEBUG_BUILD && logger.warn('Discarded request mode session because autoSessionTracking option was disabled');
} else {
this._sessionFlusher.incrementSessionStatusCount();
}
}
/**
* @inheritDoc
*/
_prepareEvent(
event,
hint,
scope,
isolationScope,
) {
if (this._options.platform) {
event.platform = event.platform || this._options.platform;
}
if (this._options.runtime) {
event.contexts = {
...event.contexts,
runtime: (event.contexts || {}).runtime || this._options.runtime,
};
}
if (this._options.serverName) {
event.server_name = event.server_name || this._options.serverName;
}
return super._prepareEvent(event, hint, scope, isolationScope);
}
/** Extract trace information from scope */
_getTraceInfoFromScope(
scope,
) {
if (!scope) {
return [undefined, undefined];
}
const span = _getSpanForScope(scope);
if (span) {
const rootSpan = getRootSpan(span);
const samplingContext = getDynamicSamplingContextFromSpan(rootSpan);
return [samplingContext, spanToTraceContext(rootSpan)];
}
const { traceId, spanId, parentSpanId, dsc } = scope.getPropagationContext();
const traceContext = {
trace_id: traceId,
span_id: spanId,
parent_span_id: parentSpanId,
};
if (dsc) {
return [dsc, traceContext];
}
return [getDynamicSamplingContextFromClient(traceId, this), traceContext];
}
}
export { ServerRuntimeClient };
//# sourceMappingURL=server-runtime-client.js.map