UNPKG

@sentry/core

Version:
254 lines (218 loc) 7.83 kB
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, }; } 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