@sentry/core
Version:
Base implementation for all Sentry JavaScript SDKs
190 lines (168 loc) • 5.59 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const currentScopes = require('../../currentScopes.js');
const semanticAttributes = require('../../semanticAttributes.js');
const trace = require('../../tracing/trace.js');
const attributeExtraction = require('./attributeExtraction.js');
const attributes = require('./attributes.js');
const methodConfig = require('./methodConfig.js');
const piiFiltering = require('./piiFiltering.js');
/**
* Span creation and management functions for MCP server instrumentation
*
* Provides unified span creation following OpenTelemetry MCP semantic conventions and our opinitionated take on MCP.
* Handles both request and notification spans with attribute extraction.
*/
/**
* Creates a span name based on the method and target
* @internal
* @param method - MCP method name
* @param target - Optional target identifier
* @returns Formatted span name
*/
function createSpanName(method, target) {
return target ? `${method} ${target}` : method;
}
/**
* Build Sentry-specific attributes based on span type
* @internal
* @param type - Span type configuration
* @returns Sentry-specific attributes
*/
function buildSentryAttributes(type) {
let op;
let origin;
switch (type) {
case 'request':
op = attributes.MCP_SERVER_OP_VALUE;
origin = attributes.MCP_FUNCTION_ORIGIN_VALUE;
break;
case 'notification-incoming':
op = attributes.MCP_NOTIFICATION_CLIENT_TO_SERVER_OP_VALUE;
origin = attributes.MCP_NOTIFICATION_ORIGIN_VALUE;
break;
case 'notification-outgoing':
op = attributes.MCP_NOTIFICATION_SERVER_TO_CLIENT_OP_VALUE;
origin = attributes.MCP_NOTIFICATION_ORIGIN_VALUE;
break;
}
return {
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,
[semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: attributes.MCP_ROUTE_SOURCE_VALUE,
};
}
/**
* Unified builder for creating MCP spans
* @internal
* @param config - Span configuration
* @returns Created span
*/
function createMcpSpan(config) {
const { type, message, transport, extra, callback } = config;
const { method } = message;
const params = message.params ;
// Determine span name based on type and OTEL conventions
let spanName;
if (type === 'request') {
const targetInfo = methodConfig.extractTargetInfo(method, params || {});
spanName = createSpanName(method, targetInfo.target);
} else {
// For notifications, use method name directly per OpenTelemetry conventions
spanName = method;
}
const rawAttributes = {
...attributeExtraction.buildTransportAttributes(transport, extra),
[attributes.MCP_METHOD_NAME_ATTRIBUTE]: method,
...attributeExtraction.buildTypeSpecificAttributes(type, message, params),
...buildSentryAttributes(type),
};
const client = currentScopes.getClient();
const sendDefaultPii = Boolean(client?.getOptions().sendDefaultPii);
const attributes$1 = piiFiltering.filterMcpPiiFromSpanData(rawAttributes, sendDefaultPii) ;
return trace.startSpan(
{
name: spanName,
forceTransaction: true,
attributes: attributes$1,
},
callback,
);
}
/**
* Creates a span for incoming MCP notifications
* @param jsonRpcMessage - Notification message
* @param transport - MCP transport instance
* @param extra - Extra handler data
* @param callback - Span execution callback
* @returns Span execution result
*/
function createMcpNotificationSpan(
jsonRpcMessage,
transport,
extra,
callback,
) {
return createMcpSpan({
type: 'notification-incoming',
message: jsonRpcMessage,
transport,
extra,
callback,
});
}
/**
* Creates a span for outgoing MCP notifications
* @param jsonRpcMessage - Notification message
* @param transport - MCP transport instance
* @param callback - Span execution callback
* @returns Span execution result
*/
function createMcpOutgoingNotificationSpan(
jsonRpcMessage,
transport,
callback,
) {
return createMcpSpan({
type: 'notification-outgoing',
message: jsonRpcMessage,
transport,
callback,
});
}
/**
* Builds span configuration for MCP server requests
* @param jsonRpcMessage - Request message
* @param transport - MCP transport instance
* @param extra - Optional extra handler data
* @returns Span configuration object
*/
function buildMcpServerSpanConfig(
jsonRpcMessage,
transport,
extra,
)
{
const { method } = jsonRpcMessage;
const params = jsonRpcMessage.params ;
const targetInfo = methodConfig.extractTargetInfo(method, params || {});
const spanName = createSpanName(method, targetInfo.target);
const rawAttributes = {
...attributeExtraction.buildTransportAttributes(transport, extra),
[attributes.MCP_METHOD_NAME_ATTRIBUTE]: method,
...attributeExtraction.buildTypeSpecificAttributes('request', jsonRpcMessage, params),
...buildSentryAttributes('request'),
};
const client = currentScopes.getClient();
const sendDefaultPii = Boolean(client?.getOptions().sendDefaultPii);
const attributes$1 = piiFiltering.filterMcpPiiFromSpanData(rawAttributes, sendDefaultPii) ;
return {
name: spanName,
op: attributes.MCP_SERVER_OP_VALUE,
forceTransaction: true,
attributes: attributes$1,
};
}
exports.buildMcpServerSpanConfig = buildMcpServerSpanConfig;
exports.createMcpNotificationSpan = createMcpNotificationSpan;
exports.createMcpOutgoingNotificationSpan = createMcpOutgoingNotificationSpan;
//# sourceMappingURL=spans.js.map