Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.incubator.semconv.genai;

import com.google.auto.value.AutoValue;

@AutoValue
public abstract class CaptureMessageOptions {

public abstract boolean captureMessageContent();

public abstract boolean emitExperimentalConventions();

public static CaptureMessageOptions create(
boolean captureMessageContent, boolean emitExperimentalConventions) {
return new AutoValue_CaptureMessageOptions(captureMessageContent, emitExperimentalConventions);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.incubator.semconv.genai;

import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import javax.annotation.Nullable;

/**
* Extractor of <a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-agent-spans/">
* GenAI agent attributes</a>.
*
* <p>This class delegates to a type-specific {@link GenAiAgentAttributesGetter} for individual
* attribute extraction from request/response objects.
*/
public final class GenAiAgentAttributesExtractor<REQUEST, RESPONSE>
implements AttributesExtractor<REQUEST, RESPONSE> {

// copied from GenAiIncubatingAttributes
private static final AttributeKey<String> GEN_AI_AGENT_DESCRIPTION =
stringKey("gen_ai.agent.description");
private static final AttributeKey<String> GEN_AI_AGENT_ID = stringKey("gen_ai.agent.id");
private static final AttributeKey<String> GEN_AI_AGENT_NAME = stringKey("gen_ai.agent.name");
private static final AttributeKey<String> GEN_AI_DATA_SOURCE_ID =
stringKey("gen_ai.data_source.id");

/** Creates the GenAI agent attributes extractor. */
public static <REQUEST, RESPONSE> AttributesExtractor<REQUEST, RESPONSE> create(
GenAiAgentAttributesGetter<REQUEST, RESPONSE> attributesGetter) {
return new GenAiAgentAttributesExtractor<>(attributesGetter);
}

private final GenAiAgentAttributesGetter<REQUEST, RESPONSE> getter;

private GenAiAgentAttributesExtractor(GenAiAgentAttributesGetter<REQUEST, RESPONSE> getter) {
this.getter = getter;
}

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
internalSet(attributes, GEN_AI_AGENT_DESCRIPTION, getter.getDescription(request));
internalSet(attributes, GEN_AI_AGENT_ID, getter.getId(request));
internalSet(attributes, GEN_AI_AGENT_NAME, getter.getName(request));
internalSet(attributes, GEN_AI_DATA_SOURCE_ID, getter.getDataSourceId(request));
}

@Override
public void onEnd(
AttributesBuilder attributes,
Context context,
REQUEST request,
@Nullable RESPONSE response,
@Nullable Throwable error) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.incubator.semconv.genai;

import javax.annotation.Nullable;

/**
* An interface for getting GenAI agent attributes.
*
* <p>Instrumentation authors will create implementations of this interface for their specific
* library/framework. It will be used by the {@link GenAiAgentAttributesExtractor} to obtain the
* various GenAI agent attributes in a type-generic way.
*/
public interface GenAiAgentAttributesGetter<REQUEST, RESPONSE>
extends GenAiAttributesGetter<REQUEST, RESPONSE> {

@Nullable
String getName(REQUEST request);

@Nullable
String getDescription(REQUEST request);

@Nullable
String getId(REQUEST request);

@Nullable
String getDataSourceId(REQUEST request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ public final class GenAiAttributesExtractor<REQUEST, RESPONSE>
implements AttributesExtractor<REQUEST, RESPONSE> {

// copied from GenAiIncubatingAttributes
private static final AttributeKey<String> GEN_AI_CONVERSATION_ID =
stringKey("gen_ai.conversation.id");
static final AttributeKey<String> GEN_AI_OPERATION_NAME = stringKey("gen_ai.operation.name");
private static final AttributeKey<String> GEN_AI_OUTPUT_TYPE = stringKey("gen_ai.output.type");
static final AttributeKey<String> GEN_AI_PROVIDER_NAME = stringKey("gen_ai.provider.name");
private static final AttributeKey<Long> GEN_AI_REQUEST_CHOICE_COUNT =
longKey("gen_ai.request.choice.count");
private static final AttributeKey<List<String>> GEN_AI_REQUEST_ENCODING_FORMATS =
stringArrayKey("gen_ai.request.encoding_formats");
private static final AttributeKey<Double> GEN_AI_REQUEST_FREQUENCY_PENALTY =
Expand All @@ -52,7 +58,6 @@ public final class GenAiAttributesExtractor<REQUEST, RESPONSE>
stringArrayKey("gen_ai.response.finish_reasons");
private static final AttributeKey<String> GEN_AI_RESPONSE_ID = stringKey("gen_ai.response.id");
static final AttributeKey<String> GEN_AI_RESPONSE_MODEL = stringKey("gen_ai.response.model");
static final AttributeKey<String> GEN_AI_PROVIDER_NAME = stringKey("gen_ai.provider.name");
static final AttributeKey<Long> GEN_AI_USAGE_INPUT_TOKENS = longKey("gen_ai.usage.input_tokens");
static final AttributeKey<Long> GEN_AI_USAGE_OUTPUT_TOKENS =
longKey("gen_ai.usage.output_tokens");
Expand All @@ -71,8 +76,11 @@ private GenAiAttributesExtractor(GenAiAttributesGetter<REQUEST, RESPONSE> getter

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
internalSet(attributes, GEN_AI_CONVERSATION_ID, getter.getConversationId(request));
internalSet(attributes, GEN_AI_OPERATION_NAME, getter.getOperationName(request));
internalSet(attributes, GEN_AI_OUTPUT_TYPE, getter.getOutputType(request));
internalSet(attributes, GEN_AI_PROVIDER_NAME, getter.getSystem(request));
internalSet(attributes, GEN_AI_REQUEST_CHOICE_COUNT, getter.getChoiceCount(request));
internalSet(attributes, GEN_AI_REQUEST_MODEL, getter.getRequestModel(request));
internalSet(attributes, GEN_AI_REQUEST_SEED, getter.getRequestSeed(request));
internalSet(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
* library/framework. It will be used by the {@link GenAiAttributesExtractor} to obtain the various
* GenAI attributes in a type-generic way.
*/
public interface GenAiAttributesGetter<REQUEST, RESPONSE> {
String getOperationName(REQUEST request);
public interface GenAiAttributesGetter<REQUEST, RESPONSE>
extends GenAiOperationAttributesGetter<REQUEST, RESPONSE> {

String getSystem(REQUEST request);

Expand Down Expand Up @@ -50,6 +50,21 @@ public interface GenAiAttributesGetter<REQUEST, RESPONSE> {
@Nullable
Double getRequestTopP(REQUEST request);

@Nullable
default Long getChoiceCount(REQUEST request) {
return null;
}

@Nullable
default String getOutputType(REQUEST request) {
return null;
}

@Nullable
default String getConversationId(REQUEST request) {
return null;
}

List<String> getResponseFinishReasons(REQUEST request, @Nullable RESPONSE response);

@Nullable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.incubator.semconv.genai;

import javax.annotation.Nullable;

/**
* An interface for getting GenAI operation attributes.
*
* <p>Instrumentation authors will create implementations of this interface for their specific
* library/framework. It will be used by the {@link GenAiAttributesExtractor} to obtain the various
* GenAI attributes in a type-generic way. It will also be used by the {@link
* GenAiSpanNameExtractor} to generate span name in a type-generic way.
*/
public interface GenAiOperationAttributesGetter<REQUEST, RESPONSE> {

String getOperationName(REQUEST request);

@Nullable
String getOperationTarget(REQUEST request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,33 @@ public final class GenAiSpanNameExtractor<REQUEST> implements SpanNameExtractor<

/**
* Returns a {@link SpanNameExtractor} that constructs the span name according to GenAI semantic
* conventions: {@code <gen_ai.operation.name> <gen_ai.request.model>}.
* conventions.
*
* <ul>
* <li>Inference - {@code <gen_ai.operation.name> <gen_ai.request.model>}.
* <li>Embeddings - {@code <gen_ai.operation.name> <gen_ai.request.model>}.
* <li>Execute tool - {@code execute_tool <gen_ai.tool.name>}.
* <li>Create/Invoke agent - {@code <gen_ai.operation.name> <gen_ai.agent.name>}.
* </ul>
*/
public static <REQUEST> SpanNameExtractor<REQUEST> create(
GenAiAttributesGetter<REQUEST, ?> attributesGetter) {
GenAiOperationAttributesGetter<REQUEST, ?> attributesGetter) {
return new GenAiSpanNameExtractor<>(attributesGetter);
}

private final GenAiAttributesGetter<REQUEST, ?> getter;
private final GenAiOperationAttributesGetter<REQUEST, ?> getter;

private GenAiSpanNameExtractor(GenAiAttributesGetter<REQUEST, ?> getter) {
private GenAiSpanNameExtractor(GenAiOperationAttributesGetter<REQUEST, ?> getter) {
this.getter = getter;
}

@Override
public String extract(REQUEST request) {
String operation = getter.getOperationName(request);
String model = getter.getRequestModel(request);
if (model == null) {
String operationTarget = getter.getOperationTarget(request);
if (operationTarget == null) {
return operation;
}
return operation + ' ' + model;
return operation + ' ' + operationTarget;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.incubator.semconv.genai;

import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.instrumentation.api.incubator.semconv.genai.GenAiAttributesExtractor.GEN_AI_OPERATION_NAME;
import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import javax.annotation.Nullable;

/**
* Extractor of <a
* href="https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/#execute-tool-span">GenAI
* tool attributes</a>.
*
* <p>This class delegates to a type-specific {@link GenAiToolAttributesGetter} for individual
* attribute extraction from request/response objects.
*/
public class GenAiToolAttributesExtractor<REQUEST, RESPONSE>
implements AttributesExtractor<REQUEST, RESPONSE> {

// copied from GenAiIncubatingAttributes
private static final AttributeKey<String> GEN_AI_TOOL_CALL_ID = stringKey("gen_ai.tool.call.id");
private static final AttributeKey<String> GEN_AI_TOOL_DESCRIPTION =
stringKey("gen_ai.tool.description");
private static final AttributeKey<String> GEN_AI_TOOL_NAME = stringKey("gen_ai.tool.name");
private static final AttributeKey<String> GEN_AI_TOOL_TYPE = stringKey("gen_ai.tool.type");

/** Creates the GenAI tool attributes extractor. */
public static <REQUEST, RESPONSE> AttributesExtractor<REQUEST, RESPONSE> create(
GenAiToolAttributesGetter<REQUEST, RESPONSE> attributesGetter) {
return new GenAiToolAttributesExtractor<>(attributesGetter);
}

private final GenAiToolAttributesGetter<REQUEST, RESPONSE> getter;

private GenAiToolAttributesExtractor(GenAiToolAttributesGetter<REQUEST, RESPONSE> getter) {
this.getter = getter;
}

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
internalSet(attributes, GEN_AI_OPERATION_NAME, getter.getOperationName(request));
internalSet(attributes, GEN_AI_TOOL_DESCRIPTION, getter.getToolDescription(request));
internalSet(attributes, GEN_AI_TOOL_NAME, getter.getToolName(request));
internalSet(attributes, GEN_AI_TOOL_TYPE, getter.getToolType(request));
}

@Override
public void onEnd(
AttributesBuilder attributes,
Context context,
REQUEST request,
@Nullable RESPONSE response,
@Nullable Throwable error) {
internalSet(attributes, GEN_AI_TOOL_CALL_ID, getter.getToolCallId(request, response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.incubator.semconv.genai;

import javax.annotation.Nullable;

/**
* An interface for getting GenAI tool attributes.
*
* <p>Instrumentation authors will create implementations of this interface for their specific
* library/framework. It will be used by the {@link GenAiToolAttributesExtractor} to obtain the
* various GenAI tool attributes in a type-generic way.
*/
public interface GenAiToolAttributesGetter<REQUEST, RESPONSE>
extends GenAiOperationAttributesGetter<REQUEST, RESPONSE> {

String getToolDescription(REQUEST request);

String getToolName(REQUEST request);

String getToolType(REQUEST request);

@Nullable
String getToolCallId(REQUEST request, @Nullable RESPONSE response);
}
Loading
Loading