MCPcopy Create free account
hub / github.com/getsentry/sentry-javascript / instrumentMethod

Function instrumentMethod

packages/core/src/tracing/openai/index.ts:146–235  ·  view source on GitHub ↗

* Instrument a method with Sentry spans * Following Sentry AI Agents Manual Instrumentation conventions * @see https://docs.sentry.io/platforms/javascript/guides/node/tracing/instrumentation/ai-agents-module/#manual-instrumentation

(
  originalMethod: (...args: T) => Promise<R>,
  methodPath: string,
  instrumentedMethod: InstrumentedMethodEntry,
  context: unknown,
  options: OpenAiOptions,
)

Source from the content-addressed store, hash-verified

144 * @see https://docs.sentry.io/platforms/javascript/guides/node/tracing/instrumentation/ai-agents-module/#manual-instrumentation
145 */
146function instrumentMethod<T extends unknown[], R>(
147 originalMethod: (...args: T) => Promise<R>,
148 methodPath: string,
149 instrumentedMethod: InstrumentedMethodEntry,
150 context: unknown,
151 options: OpenAiOptions,
152): (...args: T) => Promise<R> {
153 return function instrumentedCall(...args: T): Promise<R> {
154 const operationName = instrumentedMethod.operation || 'unknown';
155 const requestAttributes = extractRequestAttributes(args, operationName);
156 const model = (requestAttributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] as string) || 'unknown';
157
158 const params = args[0] as Record<string, unknown> | undefined;
159 const isStreamRequested = params && typeof params === 'object' && params.stream === true;
160
161 const spanConfig = {
162 name: `${operationName} ${model}`,
163 op: `gen_ai.${operationName}`,
164 attributes: requestAttributes as Record<string, SpanAttributeValue>,
165 };
166
167 if (isStreamRequested) {
168 let originalResult!: Promise<R>;
169
170 const instrumentedPromise = startSpanManual(spanConfig, (span: Span) => {
171 originalResult = originalMethod.apply(context, args);
172
173 if (options.recordInputs && params) {
174 addRequestAttributes(span, params, operationName, shouldEnableTruncation(options.enableTruncation));
175 }
176
177 // Return async processing
178 return (async () => {
179 try {
180 const result = await originalResult;
181 return instrumentStream(
182 result as OpenAIStream<ChatCompletionChunk | ResponseStreamingEvent>,
183 span,
184 options.recordOutputs ?? false,
185 ) as unknown as R;
186 } catch (error) {
187 span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
188 captureException(error, {
189 mechanism: {
190 handled: false,
191 type: 'auto.ai.openai.stream',
192 data: { function: methodPath },
193 },
194 });
195 span.end();
196 throw error;
197 }
198 })();
199 });
200
201 return wrapPromiseWithMethods(originalResult, instrumentedPromise, 'auto.ai.openai');
202 }
203

Callers 1

getFunction · 0.70

Calls 13

startSpanManualFunction · 0.90
shouldEnableTruncationFunction · 0.90
instrumentStreamFunction · 0.90
captureExceptionFunction · 0.90
wrapPromiseWithMethodsFunction · 0.90
startSpanFunction · 0.90
addResponseAttributesFunction · 0.90
addRequestAttributesFunction · 0.85
extractRequestAttributesFunction · 0.70
setStatusMethod · 0.65
endMethod · 0.65
applyMethod · 0.45

Tested by

no test coverage detected