Blades provides powerful observability capabilities for AI Agent applications, including Tracing (distributed tracing) and performance visualization. By integrating OpenTelemetry, you can easily obtain call chains, time consumption statistics, and insights into system behavior. This article is based on the example code: 🔗 https://github.com/go-kratos/blades/blob/main/examples/middleware-otel/main.go
Ensure you have installed Go 1.20+ and introduced dependencies in your project:
go get github.com/go-kratos/bladesgo get github.com/go-kratos/blades/contrib/otelgo get go.opentelemetry.io/otelgo get go.opentelemetry.io/otel/sdk/tracego get go.opentelemetry.io/otel/exporters/stdout/stdouttraceIf you want to connect to OpenTelemetry Collector, Jaeger, or Zipkin, simply replace the Exporter.
The following shows how to initialize an OpenTelemetry TracerProvider for recording and exporting trace data:
// Create and initialize OpenTelemetry TracerProviderfunc createTracerProvider() func(context.Context) error { exporter, err := stdouttrace.New( stdouttrace.WithPrettyPrint(), ) if err != nil { log.Fatal(err) }
resource, err := resource.New(context.Background(), resource.WithAttributes( semconv.ServiceNameKey.String("blades-performance-monitoring"), ), ) if err != nil { log.Fatal(err) }
tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter, sdktrace.WithBatchTimeout(1*time.Millisecond)), sdktrace.WithResource(resource), )
otel.SetTracerProvider(tp)
// Return shutdown method to release in main() return tp.Shutdown}Function Analysis
Blades provides a unified middleware mechanism that automatically generates trace spans before and after Agent calls.
Example:
// Configure OpenAI API key and base URL using environment variables:model := openai.NewModel("gpt-5", openai.Config{ APIKey: os.Getenv("OPENAI_API_KEY"),})agent := blades.NewAgent( "Example Agent", blades.WithModel(model), blades.WithInstruction("Answer briefly."), blades.WithMiddleware( middleware.Tracing( middleware.WithSystem("openai"), // Optional label, identifies backend ), ),)Complete runnable example code:
package main
import ( "context" "log" "time"
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.34.0"
"github.com/go-kratos/blades" "github.com/go-kratos/blades/contrib/openai" middleware "github.com/go-kratos/blades/contrib/otel")
func main() { exporter, err := stdouttrace.New() if err != nil { log.Fatal(err) } resource, err := resource.New(context.Background(), resource.WithAttributes( semconv.ServiceNameKey.String("otel-demo"), ), ) if err != nil { log.Fatal(err) } otel.SetTracerProvider( sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter, sdktrace.WithBatchTimeout(15*time.Second)), sdktrace.WithResource(resource), ), ) // Create a blades agent with OpenTelemetry middleware model := openai.NewModel("gpt-5", openai.Config{ APIKey: os.Getenv("OPENAI_API_KEY"), }) agent, err := blades.NewAgent( "OpenTelemetry Agent", blades.WithModel(model), blades.WithMiddleware(middleware.Tracing()), ) if err != nil { log.Fatal(err) } input := blades.UserMessage("Write a diary about spring, within 100 words") runner := blades.NewRunner(agent) msg, err := runner.Run(context.Background(), input) if err != nil { log.Fatal(err) } log.Println(msg.Text()) // Shutdown the exporter to flush any remaining spans if err := exporter.Shutdown(context.Background()); err != nil { log.Fatal(err) }}Through the examples in this article, you can:
You can extend this to:
Blades provides an out-of-the-box observability system, making AI Agent projects easier to analyze, troubleshoot, and optimize in production environments.