Manual Instrumentation
Export spans from any OpenTelemetry SDK to Confident AI and set confident.* attributes by hand
Manual instrumentation means creating OpenTelemetry spans yourself with a raw OpenTelemetry SDK and exporting them to Confident AI's OTLP endpoint, without going through confident-trace's tracing helpers.
Overview
confident-trace is built on
OpenTelemetry. Calling init() already
configures the Confident AI exporter, and spans from its automatic integrations
and tracing helpers are exported as OpenTelemetry spans by default.
This page is for manually instrumenting an application with the OpenTelemetry
SDK: for example, when your language isn't supported by confident-trace, your
application already owns its telemetry pipeline, or you prefer a raw
OpenTelemetry tracer over the span and trace-context helpers. You can also mix
manual OpenTelemetry spans with confident-trace spans in the same trace.
Confident AI receives OTLP traces at https://otel.confident-ai.com. To export
traces with a raw OpenTelemetry SDK, configure an OTLP exporter using the steps
below.
Quickstart
The following quickstart exports manually created spans to the Confident AI OTLP endpoint, where they appear in the Observatory.
Set Environment Variables
First set
CONFIDENT_API_KEYandOTEL_EXPORTER_OTLP_ENDPOINTas environment variables:Bash export CONFIDENT_API_KEY="confident_us..." export OTEL_EXPORTER_OTLP_ENDPOINT="https://otel.confident-ai.com"Trace your first LLM application
Install opentelemetry dependencies:
Bash pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-httpRun the following code:
main.py import json import os from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter OTLP_ENDPOINT = os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT") CONFIDENT_API_KEY = os.getenv("CONFIDENT_API_KEY") trace_provider = TracerProvider() exporter = OTLPSpanExporter( endpoint=f"{OTLP_ENDPOINT}/v1/traces", headers={"x-confident-api-key": CONFIDENT_API_KEY}, ) span_processor = BatchSpanProcessor(span_exporter=exporter) trace_provider.add_span_processor(span_processor) tracer = trace_provider.get_tracer("application_tracer") # Start a span with tracer.start_as_current_span("confident-llm-span") as span: # Set attributes span.set_attribute("confident.trace.name", "example-trace") span.set_attribute("confident.span.type", "llm") span.set_attribute("gen_ai.request.model", "gpt-4o") span.set_attribute("confident.span.input", json.dumps("What is the capital of France?")) span.set_attribute("confident.span.output", json.dumps("Paris")) trace_provider.force_flush() print("Traces posted successfully to https://otel.confident-ai.com")Run the code:
python main.pyInstall Node.js dependencies
npm init -y npm install @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-proto dotenvInstall TypeScript and ts-node
npm install -D typescript ts-node @types/nodeCreate
index.tsfile. This file contains the code for creating an LLM span.index.ts import * as opentelemetry from '@opentelemetry/api'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'; // Environment variables (similar to Python's os.getenv) const OTLP_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_ENDPOINT; const CONFIDENT_API_KEY = process.env.CONFIDENT_API_KEY; // Add validation for required environment variables if (!OTLP_ENDPOINT) { throw new Error('OTEL_EXPORTER_OTLP_ENDPOINT environment variable is required'); } // Create OTLP exporter with HTTPS support const otlpExporter = new OTLPTraceExporter({ url: `${OTLP_ENDPOINT}/v1/traces`, headers: { 'x-confident-api-key': CONFIDENT_API_KEY || '' }, }); // Set up the tracer provider with the batch span processor const provider = new NodeTracerProvider({ spanProcessors: [new BatchSpanProcessor(otlpExporter)] }); // Register the provider globally opentelemetry.trace.setGlobalTracerProvider(provider); // Create a tracer const tracer = opentelemetry.trace.getTracer('confident-llm-tracer'); async function main() { // Start a span tracer.startActiveSpan('confident-llm-span-typescript', (span) => { // Set attributes span.setAttributes({ 'confident.trace.name': 'example-trace', 'confident.span.type': 'llm', 'gen_ai.request.model': 'gpt-4o', 'confident.span.input': JSON.stringify('What is the capital of France?'), 'confident.span.output': JSON.stringify('Paris') }); // Simulate some work here console.log('Processing LLM request...'); // End the span span.end(); }); // Shut down the provider to ensure traces are flushed before the script exits await provider.shutdown(); console.log(`Trace posted successfully to ${OTLP_ENDPOINT}.`); } main().catch((error) => { console.error('Error sending traces:', error); process.exit(1); });Create a basic
tsconfig.jsonfile:tsconfig.json { "compilerOptions": { "target": "ES2020", "module": "commonjs", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist" } }Run the code:
npx ts-node index.tsInstall Go (version 1.19 or later recommended):
Set up environment variables:
export OTEL_EXPORTER_OTLP_ENDPOINT="https://otel.confident-ai.com" export CONFIDENT_API_KEY="<your-confident-api-key>"Initialize Go Module:
go mod init go-exampleCreate
main.gofile.main.go package main import ( "context" "fmt" "log" "os" "strconv" "strings" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) func main() { endpoint := strings.TrimRight(os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"), "/") + "/v1/traces" confidentApiKey := os.Getenv("CONFIDENT_API_KEY") exporter, err := otlptracehttp.New(context.Background(), otlptracehttp.WithEndpointURL(endpoint), otlptracehttp.WithHeaders(map[string]string{"x-confident-api-key": confidentApiKey}), ) if err != nil { log.Fatalf("failed to create OTLP exporter: %v", err) } tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter)) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) defer func() { fmt.Println("Shutting down tracer provider...") _ = tp.Shutdown(context.Background()) }() _, span := otel.Tracer("example.com/otel-openai").Start(context.Background(), "chat gpt-4o") defer func() { span.End() fmt.Println("Span ended - Trace posted successfully to:", endpoint) }() span.SetAttributes( attribute.String("confident.span.type", "llm"), attribute.String("gen_ai.request.model", "gpt-4o"), attribute.String("confident.span.input", strconv.Quote("input")), attribute.String("confident.span.output", strconv.Quote("output")), ) }Install dependencies:
go mod tidyRun the code:
go run main.goCreate
Gemfilefile. This file contains the dependencies for the Ruby application.Gemfile source 'https://rubygems.org' gem 'opentelemetry-sdk' gem 'opentelemetry-exporter-otlp'Install dependencies:
bundle installCreate
example.rbfile. This file contains the code for creating an LLM span.example.rb require 'json' require 'opentelemetry/sdk' require 'opentelemetry/exporter/otlp' # Ensure OTLP endpoint and API key are set OTLP_ENDPOINT = ENV.fetch('OTEL_EXPORTER_OTLP_ENDPOINT') { abort 'Set OTEL_EXPORTER_OTLP_ENDPOINT' } CONFIDENT_API_KEY = ENV.fetch('CONFIDENT_API_KEY') { abort 'Set CONFIDENT_API_KEY' } OpenTelemetry::SDK.configure do |c| c.add_span_processor( OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new( OpenTelemetry::Exporter::OTLP::Exporter.new( endpoint: "#{OTLP_ENDPOINT}/v1/traces", headers: { 'x-confident-api-key' => CONFIDENT_API_KEY }, ) ) ) end tracer = OpenTelemetry.tracer_provider.tracer(__FILE__) tracer.in_span('confident-llm-span-ruby') do |span| span.set_attribute('confident.trace.name', 'example-trace') span.set_attribute('confident.span.type', 'llm') span.set_attribute('gen_ai.request.model', 'gpt-4o') span.set_attribute('confident.span.input', 'What is the capital of France?'.to_json) span.set_attribute('confident.span.output', 'Paris'.to_json) puts 'Span created successfully!' end # Flush and allow time for HTTP export OpenTelemetry.tracer_provider.shutdown puts "Traces posted successfully to #{OTLP_ENDPOINT}." sleep 2Run the code:
ruby example.rbCreate a New Console App
dotnet new console -n ConfidentLLMExample cd ConfidentLLMExampleAdd Required NuGet Packages
dotnet add package OpenTelemetry dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocolCreate
Program.csfile. This file contains the code for creating an LLM span.Program.cs using System; using OpenTelemetry; using OpenTelemetry.Trace; using OpenTelemetry.Resources; using OpenTelemetry.Exporter; using System.Text.Json; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var otlpEndpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT"); var confidentApiKey = Environment.GetEnvironmentVariable("CONFIDENT_API_KEY"); Console.WriteLine($"OTLP Endpoint: {otlpEndpoint}"); Console.WriteLine($"API Key configured: {!string.IsNullOrEmpty(confidentApiKey)}"); using var tracerProvider = Sdk.CreateTracerProviderBuilder() .SetResourceBuilder(ResourceBuilder.CreateDefault() .AddService("ConfidentLLMService")) .AddSource("ConfidentLLMTracer") .AddOtlpExporter(options => { options.Endpoint = new Uri($"{otlpEndpoint}/v1/traces"); options.Headers = $"x-confident-api-key={confidentApiKey}"; options.Protocol = OtlpExportProtocol.HttpProtobuf; // Add timeout and retry configuration options.TimeoutMilliseconds = 30000; }) .Build(); var tracer = tracerProvider.GetTracer("ConfidentLLMTracer"); Console.WriteLine("Starting span..."); using (var currentSpan = tracer.StartActiveSpan("confident-llm-span-csharp")) { currentSpan.SetAttribute("confident.trace.name", "example-trace"); currentSpan.SetAttribute("confident.span.type", "llm"); currentSpan.SetAttribute("gen_ai.request.model", "gpt-4o"); currentSpan.SetAttribute("confident.span.input", JsonSerializer.Serialize("What is the capital of France?")); currentSpan.SetAttribute("confident.span.output", JsonSerializer.Serialize("Paris")); Console.WriteLine("Span created with attributes. It will end after 5 seconds."); await Task.Delay(5000); } Console.WriteLine("Span ended. Flushing traces..."); // Force flush traces before exiting tracerProvider.ForceFlush(); // Wait a bit to ensure traces are sent await Task.Delay(2000); Console.WriteLine($"Trace posted successfully to {otlpEndpoint}."); } }Build and Run
dotnet run
🎉 Congratulations! You have successfully sent traces. Open the Observatory in Confident AI to view them.
Click to see the native Python implementation using confident-trace
If your app is in a language confident-trace supports, you don't have to hand-build the exporter above — confident-trace is OpenTelemetry under the hood and ships a pre-configured export pipeline for Confident AI. init() sets up the provider, exporter, endpoint, and API key header for you, and the confident.* attributes on this page work exactly the same on spans you create with a plain OpenTelemetry tracer.
Install confident-trace and set CONFIDENT_API_KEY, then:
import json
from confident_trace import init, shutdown
from opentelemetry import trace
init(instrumentations=())
tracer = trace.get_tracer("my-application")
try:
with tracer.start_as_current_span("request") as current:
current.set_attribute("confident.trace.name", "example-trace")
current.set_attribute("confident.span.type", "llm")
current.set_attribute("gen_ai.request.model", "gpt-4o")
current.set_attribute("confident.span.input", json.dumps("What is the capital of France?"))
current.set_attribute("confident.span.output", json.dumps("Paris"))
finally:
shutdown()If your application already owns a TracerProvider, see existing OpenTelemetry provider below instead of letting init() create one.
Existing OpenTelemetry Provider
If your application already owns a TracerProvider — because you export to another observability backend, or run the OpenTelemetry Collector — you don't need a second one. confident-trace adds its export pipeline to the provider you already have, so your sampler, resource attributes, and other span processors are kept, and your application stays responsible for the provider lifecycle (including flushing and shutting it down).
Pass your provider to init():
from confident_trace import init
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
provider = TracerProvider()
trace.set_tracer_provider(provider) # so other libraries use it too
init(tracer_provider=provider)Everything else about init() — automatic integrations, CONFIDENT_API_KEY,
CONFIDENT_OTEL_ENDPOINT, and sampling — works as usual; the only
difference is that spans flow through your provider.
Add Confident AI's span processor when constructing the provider, and don't call init():
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
import { createSpanProcessor } from "confident-trace/otel";
const provider = new NodeTracerProvider({
spanProcessors: [createSpanProcessor()],
});
provider.register();
// After all application work finishes:
await provider.shutdown();Set CONFIDENT_API_KEY (and CONFIDENT_OTEL_ENDPOINT if you're on the EU
region or self-hosting) in the environment as you would for init().
Understanding OTEL with Confident AI
The rest of this page is an attribute reference. It covers:
- Confident AI's
confident.trace.*andconfident.span.*attributes - The
gen_ai.*attributes Confident AI reads for LLM and tool spans - Environment and other resource-level configuration
For how the OTLP endpoint works, and how Confident AI maps gen_ai.*,
OpenInference, and OpenLLMetry spans onto its data model, see the
OpenTelemetry overview.
OTEL endpoints
Confident AI offers the https://otel.confident-ai.com endpoint that accepts OpenTelemetry traces in the OTLP format. Please note that Confident AI does not support GRPC for the OpenTelemetry endpoint. Please use HTTP instead. See regions and endpoints for the EU and self-hosted hosts.
Attributes
Confident AI adheres to the GenAI semantic convention and adds an extra layer on top of it to capture additional data about the LLM applications. Confident AI uses confident.* namespace to map specific attributes with llm tracing data model. These specific attributes always take precedence over gen_ai.* conventions and are recommended for all users that are manually instrumenting their applications. The full precedence order is documented in attribute precedence.
Environment
Set the environment as an OpenTelemetry resource attribute when you configure the SDK:
OTEL_RESOURCE_ATTRIBUTES="confident.trace.environment=production"Trace-Level Attribute Mappings
These are the attributes specific to Confident AI traces similar to tracing features. The trace level attributes are set in the span attributes using the confident.trace.* namespace.
Name
The trace name is displayed in the UI. You can customize it based on your liking for better UI display using the following attribute:
"confident.trace.name"(of typestr) used for updating trace name
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.name", "test_trace")span.setAttributes({
"confident.trace.name": "example-trace",
});span.SetAttributes(
attribute.String("confident.trace.name", "example-trace"),
)span.set_attribute("confident.trace.name", "example-trace")span.SetAttribute("confident.trace.name", "example-trace");Input/Output
You can set trace input and output at runtime using the following attributes:
"confident.trace.input"(JSON string) sets the trace input"confident.trace.output"(JSON string) sets the trace output
In the examples below, input and output are already JSON-serialized strings.
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.input", input)
span.set_attribute("confident.trace.output", output)span.setAttributes({
"confident.trace.input": input,
"confident.trace.output": output,
});span.SetAttributes(
attribute.String("confident.trace.input", input),
attribute.String("confident.trace.output", output),
)span.set_attribute("confident.trace.input", input)
span.set_attribute("confident.trace.output", output)span.SetAttribute("confident.trace.input", input);
span.SetAttribute("confident.trace.output", output);Test Case
Online evaluations are selected with
Evaluation Rules in Confident AI. Set the test case parameters on the trace
using confident.trace.* attributes:
import json
with tracer.start_as_current_span("confident_evaluation") as span:
input = "What is the capital of France?"
output = my_llm_app(input) # your LLM application
span.set_attribute('confident.trace.input', json.dumps(input))
span.set_attribute('confident.trace.output', json.dumps(output))
span.set_attribute('confident.trace.retrieval_context', json.dumps(["context1", "context2"]))
span.set_attribute('confident.trace.expected_output', json.dumps("Paris"))span.setAttributes({
"confident.trace.input": JSON.stringify(input),
"confident.trace.output": JSON.stringify(output),
"confident.trace.retrieval_context": JSON.stringify(["context1", "context2"]),
"confident.trace.expected_output": JSON.stringify("Paris"),
});span.SetAttributes(
attribute.String("confident.trace.input", `"What is the capital of France?"`),
attribute.String("confident.trace.output", `"Paris"`),
attribute.String("confident.trace.retrieval_context", `["context1","context2"]`),
attribute.String("confident.trace.expected_output", `"Paris"`),
)span.set_attribute("confident.trace.input", input.to_json)
span.set_attribute("confident.trace.output", output.to_json)
span.set_attribute("confident.trace.retrieval_context", ["context1", "context2"].to_json)
span.set_attribute("confident.trace.expected_output", "Paris".to_json)span.SetAttribute("confident.trace.input", JsonSerializer.Serialize(input));
span.SetAttribute("confident.trace.output", JsonSerializer.Serialize(output));
span.SetAttribute("confident.trace.retrieval_context", JsonSerializer.Serialize(new[] { "context1", "context2" }));
span.SetAttribute("confident.trace.expected_output", JsonSerializer.Serialize("Paris"));LLM test case attributes mapping:
"confident.trace.input"(JSON string) sets the test case input"confident.trace.output"(JSON string) sets the test case actual output- [Optional]
"confident.trace.expected_output"(JSON string) sets the expected output - [Optional]
"confident.trace.context"(JSON-encoded string array) sets context - [Optional]
"confident.trace.retrieval_context"(JSON-encoded string array) sets retrieval context - [Optional]
"confident.trace.tools_called"(JSON-encoded tool array) sets tools called - [Optional]
"confident.trace.expected_tools"(JSON-encoded tool array) sets expected tools
Tags
Tags are simple string labels that make it easy to group related traces together, and cannot be applied to spans.
"confident.trace.tags"(of typelist[str]) used for updating trace tags
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.tags", ["tag1", "tag2"])span.setAttributes({ "confident.trace.tags": ["tag1", "tag2"] });span.SetAttributes(
attribute.StringSlice("confident.trace.tags", []string{"tag1", "tag2"}),
)span.set_attribute('confident.trace.tags', ['tag1', 'tag2'])currentSpan.SetAttribute("confident.trace.tags", new[] { "tag1", "tag2" });Metadata
Attach metadata to the trace. This information can be used for filtering, grouping, and analyzing your traces in the observatory.
"confident.trace.metadata"(of typestr) used for updating trace metadata
This attribute is a JSON string which is parsed into a dictionary.
import json
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.metadata", json.dumps({"key": "value"}))span.setAttributes({
"confident.trace.metadata": JSON.stringify({ key: "value" }),
});attribute.String("confident.trace.metadata", `{"key": "value"}`)span.set_attribute("confident.trace.metadata", '{"key":"value"}')span.SetAttribute("confident.trace.metadata", "{\"key\":\"value\"}");Thread Id
A thread on Confident AI is a collection of one or more traces, letting you view full conversations — perfect for chat apps, agents, or any multi-turn interactions.
"confident.trace.thread.id"(string) sets the thread ID"confident.trace.thread.tags"(string array) sets thread tags"confident.trace.thread.metadata"(JSON object string) sets thread metadata
confident.trace.thread_id remains a legacy ID alias. Prefer the structured
confident.trace.thread.* attributes for new manual instrumentation.
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.thread.id", "123")span.setAttributes({
"confident.trace.thread.id": "123",
});span.SetAttributes(
attribute.String("confident.trace.thread.id", "123"),
)span.set_attribute("confident.trace.thread.id", "123")span.SetAttribute("confident.trace.thread.id", "123");User Id
Track user interactions by setting user id in a trace — useful for monitoring token usage, identifying top users, and managing costs.
"confident.trace.user_id"(of typestr) used for updating trace user id
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.user_id", "123")span.setAttributes({
"confident.trace.user_id": "123",
});span.SetAttributes(
attribute.String("confident.trace.user_id", "123"),
)span.set_attribute("confident.trace.user_id", "123")span.SetAttribute("confident.trace.user_id", "123");Test Case Id
For single-turn evaluations via AI Connections, Confident AI sends a testCaseId in the payload to your endpoint. Pass it as the test_case_id attribute on your trace to link the trace back to its test case — letting you click through to the full trace directly from evaluation results.
"confident.trace.test_case_id"(of typestr) used for linking the trace to a test case in evaluation results
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.test_case_id", test_case_id)span.setAttributes({
"confident.trace.test_case_id": testCaseId,
});span.SetAttributes(
attribute.String("confident.trace.test_case_id", testCaseId),
)span.set_attribute("confident.trace.test_case_id", test_case_id)span.SetAttribute("confident.trace.test_case_id", testCaseId);Turn Id
For multi-turn evaluations via AI Connections, Confident AI sends a turnId in the payload for each turn. Pass it as the turn_id attribute on your trace to link each turn's trace to the specific turn in the conversation.
"confident.trace.turn_id"(of typestr) used for linking the trace to a specific turn in multi-turn evaluation results
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.trace.turn_id", turn_id)span.setAttributes({
"confident.trace.turn_id": turnId,
});span.SetAttributes(
attribute.String("confident.trace.turn_id", turnId),
)span.set_attribute("confident.trace.turn_id", turn_id)span.SetAttribute("confident.trace.turn_id", turnId);Span-Level Attribute Mappings
These are the attributes specific to Confident AI spans similar to tracing features. The span level attributes are set in the span attributes using the confident.span.* namespace.
Name
The span name is the standard OpenTelemetry
span name supplied when the span starts (for example, "custom_span" in
start_as_current_span("custom_span")). There is no separate
confident.span.name attribute.
Input/Output
You can set span input and output at runtime using the following attributes:
"confident.span.input"(JSON string) sets the span input"confident.span.output"(JSON string) sets the span output
In the examples below, input and output are already JSON-serialized strings.
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.span.input", input)
span.set_attribute("confident.span.output", output)span.setAttributes({
"confident.span.input": input,
"confident.span.output": output,
});span.SetAttributes(
attribute.String("confident.span.input", input),
attribute.String("confident.span.output", output),
)span.set_attribute("confident.span.input", input)
span.set_attribute("confident.span.output", output)span.SetAttribute("confident.span.input", input);
span.SetAttribute("confident.span.output", output);Test Case
Online evaluations are selected with
Evaluation Rules in Confident AI. Set the test case parameters on any span using
confident.span.* attributes:
import json
with tracer.start_as_current_span("confident_evaluation") as span:
input = "What is the capital of France?"
output = my_llm_app(input) # your LLM application
span.set_attribute('confident.span.input', json.dumps(input))
span.set_attribute('confident.span.output', json.dumps(output))
span.set_attribute('confident.span.retrieval_context', json.dumps(["context1", "context2"]))
span.set_attribute('confident.span.expected_output', json.dumps("Paris"))span.setAttributes({
"confident.span.input": JSON.stringify(input),
"confident.span.output": JSON.stringify(output),
"confident.span.retrieval_context": JSON.stringify(["context1", "context2"]),
"confident.span.expected_output": JSON.stringify("Paris"),
});span.SetAttributes(
attribute.String("confident.span.input", `"What is the capital of France?"`),
attribute.String("confident.span.output", `"Paris"`),
attribute.String("confident.span.retrieval_context", `["context1","context2"]`),
attribute.String("confident.span.expected_output", `"Paris"`),
)span.set_attribute("confident.span.input", input.to_json)
span.set_attribute("confident.span.output", output.to_json)
span.set_attribute("confident.span.retrieval_context", ["context1", "context2"].to_json)
span.set_attribute("confident.span.expected_output", "Paris".to_json)span.SetAttribute("confident.span.input", JsonSerializer.Serialize(input));
span.SetAttribute("confident.span.output", JsonSerializer.Serialize(output));
span.SetAttribute("confident.span.retrieval_context", JsonSerializer.Serialize(new[] { "context1", "context2" }));
span.SetAttribute("confident.span.expected_output", JsonSerializer.Serialize("Paris"));LLM test case attributes mapping:
"confident.span.input"(JSON string) sets the test case input"confident.span.output"(JSON string) sets the test case actual output- [Optional]
"confident.span.expected_output"(JSON string) sets the expected output - [Optional]
"confident.span.context"(JSON-encoded string array) sets context - [Optional]
"confident.span.retrieval_context"(JSON-encoded string array) sets retrieval context - [Optional]
"confident.span.tools_called"(JSON-encoded tool array) sets tools called - [Optional]
"confident.span.expected_tools"(JSON-encoded tool array) sets expected tools
Metadata
Metadata can be attached to the span. This information can be used for filtering, grouping, and analyzing your spans in the observatory.
"confident.span.metadata"(of typestr) used for updating span metadata
This attribute is a JSON string which is parsed into a dictionary.
import json
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.span.metadata", json.dumps({"key": "value"}))span.setAttributes({
"confident.span.metadata": JSON.stringify({ key: "value" }),
});span.SetAttributes(
attribute.String("confident.span.metadata", `{"key": "value"}`),
)span.set_attribute("confident.span.metadata", '{"key":"value"}')span.SetAttribute("confident.span.metadata", "{\"key\": \"value\"}");Type specific attributes
Span types are optional but allow you to classify the most common types of components in LLM applications, which includes these 4 default span types:
llmagentretrievertool
You can set the span type using the following attribute:
"confident.span.type"(of typestr) used for updating span type
with tracer.start_as_current_span("custom_span") as span:
span.set_attribute("confident.span.type", "llm")span.setAttributes({
"confident.span.type": "llm",
});span.SetAttributes(
attribute.String("confident.span.type", "llm"),
)span.set_attribute("confident.span.type", "llm")span.SetAttribute("confident.span.type", "llm");Span-Level Attributes for Specific Span Types
Type-specific data uses a combination of the standard gen_ai.* semantic
conventions and the Confident AI attributes listed below. Do not invent a
confident.{span_type}.* namespace; only the documented attributes are
recognized.
Custom
This is the default span type. All the attributes that we used above with confident.span.* namespace are applicable to this span type.
LLM
To create an LLM span, set confident.span.type to llm. See LLM
spans for the corresponding
high-level tracing API.
"gen_ai.request.model"(of typestr) records the requested model"gen_ai.provider.name"(of typestr) records the model provider"gen_ai.usage.input_tokens"(of typeint) records input token usage"gen_ai.usage.output_tokens"(of typeint) records output token usage- [Optional]
"confident.llm.cost_per_input_token"(of typefloat) used for updating cost per input token - [Optional]
"confident.llm.cost_per_output_token"(of typefloat) used for updating cost per output token
Given below is the sample code for setting attributes for LLM span type.
with tracer.start_as_current_span("llm_span") as span:
span.set_attribute("confident.span.type", "llm")
span.set_attribute("gen_ai.request.model", "gpt-4o")
span.set_attribute("gen_ai.provider.name", "openai")
span.set_attribute("confident.span.input", json.dumps([
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": input}
]))
time.sleep(0.5)
span.set_attribute("confident.span.output", json.dumps("Hello world"))span.setAttributes({
"confident.span.type": "llm",
"gen_ai.request.model": "gpt-4o",
"gen_ai.provider.name": "openai",
"confident.span.input": JSON.stringify([
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "What is the capital of France?" },
]),
"confident.span.output": JSON.stringify("Hello world"),
});span.SetAttributes(
attribute.String("confident.span.type", "llm"),
attribute.String("gen_ai.request.model", "gpt-4o"),
attribute.String("gen_ai.provider.name", "openai"),
attribute.String("confident.span.input", `[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"What is the capital of France?"}]`),
attribute.String("confident.span.output", `"Hello world"`),
)span.set_attribute("confident.span.type", "llm")
span.set_attribute("gen_ai.request.model", "gpt-4o")
span.set_attribute("gen_ai.provider.name", "openai")
span.set_attribute("confident.span.input", [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "What is the capital of France?" }
].to_json)
span.set_attribute("confident.span.output", "Hello world".to_json)span.SetAttribute("confident.span.type", "llm");
span.SetAttribute("gen_ai.request.model", "gpt-4o");
span.SetAttribute("gen_ai.provider.name", "openai");
span.SetAttribute("confident.span.input", JsonSerializer.Serialize(new[] {
new { role = "system", content = "You are a helpful assistant." },
new { role = "user", content = "What is the capital of France?" }
}));
span.SetAttribute("confident.span.output", JsonSerializer.Serialize("Hello world"));Agent
To create an Agent span, set confident.span.type to agent. Agent spans use
the shared confident.span.* fields described above and have no additional
type-specific attributes. See Agent
spans.
Given below is the sample code for setting attributes for Agent span type.
with tracer.start_as_current_span("agent_span") as span:
span.set_attribute("confident.span.type", "agent")
span.set_attribute("confident.span.input", json.dumps({"input": "input"}))
span.set_attribute("confident.span.output", json.dumps({"output": "output"}))span.setAttributes({
"confident.span.type": "agent",
"confident.span.input": JSON.stringify({ input: "input" }),
"confident.span.output": JSON.stringify({ output: "output" }),
});span.SetAttributes(
attribute.String("confident.span.input", `{"input": "input"}`),
attribute.String("confident.span.output", `{"output": "output"}`),
attribute.String("confident.span.type", "agent"),
)span.set_attribute("confident.span.type", "agent")
span.set_attribute("confident.span.input", { input: "input" }.to_json)
span.set_attribute("confident.span.output", { output: "output" }.to_json)span.SetAttribute("confident.span.type", "agent");
span.SetAttribute("confident.span.input", JsonSerializer.Serialize(new { input = "input" }));
span.SetAttribute("confident.span.output", JsonSerializer.Serialize(new { output = "output" }));Tool
To create a Tool span, set confident.span.type to tool. Set the tool name
with the standard gen_ai.tool.name attribute. See Tool
spans.
Given below is the sample code for setting attributes for Tool span type.
with tracer.start_as_current_span("tool_span") as span:
span.set_attribute("confident.span.type", "tool")
span.set_attribute("gen_ai.tool.name", "web_search")
span.set_attribute("confident.span.input", json.dumps({"input": "input"}))
span.set_attribute("confident.span.output", json.dumps({"output": "output"}))span.setAttributes({
"confident.span.type": "tool",
"gen_ai.tool.name": "web_search",
"confident.span.input": JSON.stringify({ input: "input" }),
"confident.span.output": JSON.stringify({ output: "output" }),
});span.SetAttributes(
attribute.String("gen_ai.tool.name", "web_search"),
attribute.String("confident.span.input", `{"input": "input"}`),
attribute.String("confident.span.output", `{"output": "output"}`),
attribute.String("confident.span.type", "tool"),
)span.set_attribute("confident.span.type", "tool")
span.set_attribute("gen_ai.tool.name", "web_search")
span.set_attribute("confident.span.input", { input: "input" }.to_json)
span.set_attribute("confident.span.output", { output: "output" }.to_json)span.SetAttribute("confident.span.type", "tool");
span.SetAttribute("gen_ai.tool.name", "web_search");
span.SetAttribute("confident.span.input", JsonSerializer.Serialize(new { input = "input" }));
span.SetAttribute("confident.span.output", JsonSerializer.Serialize(new { output = "output" }));Retriever
To create a Retriever span, set confident.span.type to retriever. Record
the retrieved text with confident.span.retrieval_context. See Retriever
spans.
Given below is the sample code for setting attributes for Retriever span type.
with tracer.start_as_current_span("retriever_span") as span:
span.set_attribute("confident.span.type", "retriever")
span.set_attribute("confident.span.input", json.dumps("query"))
span.set_attribute("confident.span.retrieval_context", json.dumps(["chunk 1", "chunk 2"]))span.setAttributes({
"confident.span.type": "retriever",
"confident.span.input": JSON.stringify("query"),
"confident.span.retrieval_context": JSON.stringify(["chunk 1", "chunk 2"]),
});span.SetAttributes(
attribute.String("confident.span.input", `"query"`),
attribute.String("confident.span.retrieval_context", `["chunk 1","chunk 2"]`),
attribute.String("confident.span.type", "retriever"),
)span.set_attribute("confident.span.type", "retriever")
span.set_attribute("confident.span.input", "query".to_json)
span.set_attribute("confident.span.retrieval_context", ["chunk 1", "chunk 2"].to_json)span.SetAttribute("confident.span.input", JsonSerializer.Serialize("query"));
span.SetAttribute("confident.span.retrieval_context", JsonSerializer.Serialize(new[] { "chunk 1", "chunk 2" }));Last updated on