Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
dcfff66
feat(instrumentation-openai): add instrumentation of openai SDK
anuraaga Jul 17, 2025
b58453e
Fix manifest
anuraaga Jul 17, 2025
152c2aa
Fix types
anuraaga Jul 18, 2025
20e7bad
Merge branch 'main' into openai-inst
anuraaga Jul 18, 2025
8284f96
version:update
anuraaga Jul 18, 2025
d023355
Merge branch 'openai-inst' of https://github.com/anuraaga/opentelemet…
anuraaga Jul 18, 2025
c8e58c6
Cleanups
anuraaga Jul 19, 2025
380b165
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
anuraaga Jul 19, 2025
22e806a
Fix
anuraaga Jul 19, 2025
16d44e6
Update packages/instrumentation-openai/src/utils.ts
anuraaga Jul 31, 2025
267be04
Fix debug
anuraaga Jul 31, 2025
44311d7
Merge branch 'openai-inst' of https://github.com/anuraaga/opentelemet…
anuraaga Jul 31, 2025
c6ac4ac
Comment
anuraaga Jul 31, 2025
a69be29
Regenerate semconv
anuraaga Jul 31, 2025
52c26b5
Format
anuraaga Jul 31, 2025
3ee2ed6
Fix
anuraaga Jul 31, 2025
65c2a5f
Cleanup
anuraaga Aug 1, 2025
5b0e035
git add
anuraaga Aug 1, 2025
cc1ada2
README
anuraaga Aug 1, 2025
bb28e1a
Match expect version
anuraaga Aug 1, 2025
6b90002
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
anuraaga Aug 1, 2025
c035ed2
manage to restore package-lock
anuraaga Aug 1, 2025
d6c427b
Owner
anuraaga Aug 7, 2025
36dd80b
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
anuraaga Aug 7, 2025
e89981e
Update .github.amrom.workers.devponent_owners.yml
anuraaga Aug 20, 2025
1cd03cb
Merge branch 'main' into openai-inst
anuraaga Aug 20, 2025
6d77251
Merge branch 'main' into openai-inst
pichlermarc Aug 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix types
  • Loading branch information
anuraaga committed Jul 18, 2025
commit 152c2aab6fabc9fa623f45f540c614662d7007be
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/instrumentation-openai/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
* limitations under the License.
*/
export { OpenAIInstrumentation } from './instrumentation';
export { OpenAIInstrumentationConfig } from './types';
export type { OpenAIInstrumentationConfig } from './types';
69 changes: 51 additions & 18 deletions packages/instrumentation-openai/src/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,24 @@ import {
InstrumentationNodeModuleDefinition,
} from '@opentelemetry/instrumentation';
import { SeverityNumber } from '@opentelemetry/api-logs';
import type { OpenAI } from 'openai';
import type {
ChatCompletion,
ChatCompletionMessageToolCall,
ChatCompletionContentPart,
ChatCompletionContentPartRefusal,
ChatCompletionContentPartText,
ChatCompletionCreateParams,
ChatCompletionMessageParam,
ChatCompletionChunk,
Completions as ChatCompletions,
} from 'openai/resources/chat/completions';
import type { APIPromise } from 'openai/core';
import type {
CreateEmbeddingResponse,
Embeddings,
EmbeddingCreateParams,
} from 'openai/resources/embeddings';
import type { Stream } from 'openai/streaming';

import {
ATTR_EVENT_NAME,
Expand Down Expand Up @@ -165,11 +182,11 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta

_getPatchedChatCompletionsCreate() {
const self = this;
return (original: OpenAI.Chat.Completions['create']) => {
return (original: ChatCompletions['create']) => {
// https://platform.openai.com/docs/api-reference/chat/create
return function patchedCreate(
this: OpenAI.Chat.Completions,
...args: Parameters<OpenAI.Chat.Completions['create']>
this: ChatCompletions,
...args: Parameters<ChatCompletions['create']>
) {
if (!self.isEnabled) {
return original.apply(this, args);
Expand Down Expand Up @@ -197,7 +214,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
const apiPromise = context.with(ctx, () => original.apply(this, args));

// Streaming.
if (params && params.stream) {
if (isStreamPromise(params, apiPromise)) {
// When streaming, `apiPromise` resolves to `import('openai/streaming').Stream`,
// an async iterable (i.e. has a `Symbol.asyncIterator` method). We
// want to wrap that iteration to gather telemetry. Instead of wrapping
Expand Down Expand Up @@ -228,7 +245,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
span,
startNow,
commonAttrs,
result as OpenAI.ChatCompletion,
result as ChatCompletion,
config,
ctx
);
Expand All @@ -247,7 +264,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
* as appropriate for the request params.
*/
_startChatCompletionsSpan(
params: OpenAI.ChatCompletionCreateParams,
params: ChatCompletionCreateParams,
config: OpenAIInstrumentationConfig,
baseURL: string | undefined
) {
Expand Down Expand Up @@ -303,7 +320,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta

// Capture prompts as log events.
const timestamp = Date.now();
params.messages.forEach((msg: OpenAI.ChatCompletionMessageParam) => {
params.messages.forEach((msg: ChatCompletionMessageParam) => {
switch (msg.role) {
case 'system': {
const body: GenAISystemMessageEventBody = {};
Expand Down Expand Up @@ -331,7 +348,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
if (config.captureMessageContent) {
if (Array.isArray(msg.content)) {
body.content = msg.content
.filter(p => p.type === 'text')
.filter(isTextContent)
.map(p => p.text)
.join('');
} else {
Expand All @@ -356,7 +373,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
if (msg.content) {
if (Array.isArray(msg.content)) {
body.content = msg.content
.filter(p => p.type === 'text')
.filter(isTextContent)
.map(p => p.text)
.join('');
} else {
Expand Down Expand Up @@ -433,7 +450,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
* data from those chunks, then end the span.
*/
async *_onChatCompletionsStreamIterator(
streamIter: AsyncIterator<OpenAI.ChatCompletionChunk>,
streamIter: AsyncIterator<ChatCompletionChunk>,
span: Span,
startNow: number,
config: OpenAIInstrumentationConfig,
Expand All @@ -454,7 +471,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
if (!choices[idx]) {
choices[idx] = {} as {
content: string;
toolCalls: OpenAI.ChatCompletionMessageToolCall[];
toolCalls: ChatCompletionMessageToolCall[];
};
}
if (config.captureMessageContent) {
Expand Down Expand Up @@ -582,7 +599,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
span: Span,
startNow: number,
commonAttrs: Attributes,
result: OpenAI.ChatCompletion,
result: ChatCompletion,
config: OpenAIInstrumentationConfig,
ctx: Context
) {
Expand Down Expand Up @@ -707,11 +724,11 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta

_getPatchedEmbeddingsCreate() {
const self = this;
return (original: OpenAI.Embeddings['create']) => {
return (original: Embeddings['create']) => {
// https://platform.openai.com/docs/api-reference/embeddings/create
return function patchedCreate(
this: OpenAI.Embeddings,
...args: Parameters<OpenAI.Embeddings['create']>
this: Embeddings,
...args: Parameters<Embeddings['create']>
) {
if (!self.isEnabled) {
return original.apply(this, args);
Expand Down Expand Up @@ -750,7 +767,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
* as appropriate for the request params.
*/
_startEmbeddingsSpan(
params: OpenAI.EmbeddingCreateParams,
params: EmbeddingCreateParams,
baseURL: string | undefined
) {
// Attributes common to span, metrics, log events.
Expand Down Expand Up @@ -785,7 +802,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
span: Span,
startNow: number,
commonAttrs: Attributes,
result: OpenAI.CreateEmbeddingResponse
result: CreateEmbeddingResponse
) {
debug('OpenAI.Embeddings.create result: %O', result);
try {
Expand Down Expand Up @@ -817,3 +834,19 @@ export class OpenAIInstrumentation extends InstrumentationBase<OpenAIInstrumenta
span.end();
}
}

function isTextContent(
value: ChatCompletionContentPart | ChatCompletionContentPartRefusal
): value is ChatCompletionContentPartText {
return value.type === 'text';
}

function isStreamPromise(
params: ChatCompletionCreateParams | undefined,
value: APIPromise<Stream<ChatCompletionChunk> | ChatCompletion>
): value is APIPromise<Stream<ChatCompletionChunk>> {
if (params && params.stream) {
return true;
}
return false;
}
Loading