diff --git a/contrib/google.golang.org/genai/README.md b/contrib/google.golang.org/genai/README.md new file mode 100644 index 00000000000..176973bc06a --- /dev/null +++ b/contrib/google.golang.org/genai/README.md @@ -0,0 +1,62 @@ +# Google GenAI Integration + +This integration provides Datadog LLM Observability tracing for the +[google.golang.org/genai](https://github.com/googleapis/go-genai) SDK. + +## Usage + +```go +import ( + "context" + + genaitrace "github.com/DataDog/dd-trace-go/contrib/google.golang.org/genai/v2" + "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" + "google.golang.org/genai" +) + +func main() { + tracer.Start() + defer tracer.Stop() + + raw, err := genai.NewClient(context.Background(), &genai.ClientConfig{ + APIKey: "...", + Backend: genai.BackendGeminiAPI, + }) + if err != nil { + panic(err) + } + client := genaitrace.WrapClient(raw) + + resp, err := client.Models.GenerateContent( + context.Background(), + "gemini-2.0-flash", + []*genai.Content{{Role: "user", Parts: []*genai.Part{{Text: "Hello!"}}}}, + nil, + ) + _ = resp + _ = err +} +``` + +The returned `*Client` exposes the same `Models` and `Chats` services as the +upstream SDK. For services that are not (yet) instrumented, call `Raw()` to get +the underlying `*genai.Client`. + +## Features + +The integration automatically produces LLM Observability spans for: + +- **`Models.GenerateContent`** — LLM span with prompt/response messages, + generation parameters (temperature, top_p, top_k, max_output_tokens, stop + sequences) and token usage metrics. +- **`Models.GenerateContentStream`** — LLM span covering the entire stream; + output text is reassembled from chunks and final usage metadata is captured. +- **`Models.EmbedContent`** — Embedding span with input documents and a summary + of the returned vectors. +- **`Chats.Create` / `Chat.SendMessage` / `Chat.SendMessageStream`** — LLM + spans whose input includes the existing chat history plus the new user + message. + +Spans are tagged with the model provider derived from the underlying client's +backend (`google` for Gemini API, `google_vertexai` for Vertex AI, +`google_enterprise` for the Enterprise Agent Platform). diff --git a/contrib/google.golang.org/genai/chats.go b/contrib/google.golang.org/genai/chats.go new file mode 100644 index 00000000000..070fb49dd80 --- /dev/null +++ b/contrib/google.golang.org/genai/chats.go @@ -0,0 +1,114 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace + +import ( + "context" + "iter" + + "google.golang.org/genai" +) + +// Chats wraps *genai.Client.Chats with LLM Observability tracing. +type Chats struct { + c *genai.Chats + provider string +} + +// Create creates a new chat session. The returned *Chat is a tracing wrapper; +// its SendMessage and SendMessageStream methods produce LLM spans. +func (c *Chats) Create(ctx context.Context, model string, config *genai.GenerateContentConfig, history []*genai.Content) (*Chat, error) { + if c == nil || c.c == nil { + return nil, errNilClient + } + chat, err := c.c.Create(ctx, model, config, history) + if err != nil { + return nil, err + } + return &Chat{ + chat: chat, + model: model, + provider: c.provider, + config: config, + }, nil +} + +// Chat is a tracing wrapper around *genai.Chat. +type Chat struct { + chat *genai.Chat + model string + provider string + config *genai.GenerateContentConfig +} + +// Raw returns the underlying *genai.Chat. +func (c *Chat) Raw() *genai.Chat { + if c == nil { + return nil + } + return c.chat +} + +// History delegates to the underlying *genai.Chat. +func (c *Chat) History(curated bool) []*genai.Content { + return c.chat.History(curated) +} + +// SendMessage sends a message to the chat and emits an LLM span. The input +// captured on the span is a pre-call snapshot of the chat history plus the +// new user message (genai.Chat mutates History during a successful call). +func (c *Chat) SendMessage(ctx context.Context, parts ...genai.Part) (*genai.GenerateContentResponse, error) { + if c == nil || c.chat == nil { + return nil, errNilClient + } + input := c.snapshotInput(parts) + span, ctx := startLLMSpan(ctx, "genai.chat.send_message", c.model, c.provider) + + resp, err := c.chat.SendMessage(ctx, parts...) + finishLLMSpan(span, input, c.config, resp, err) + return resp, err +} + +// SendMessageStream sends a message and streams the response, emitting an +// LLM span covering the stream. +func (c *Chat) SendMessageStream(ctx context.Context, parts ...genai.Part) iter.Seq2[*genai.GenerateContentResponse, error] { + return func(yield func(*genai.GenerateContentResponse, error) bool) { + if c == nil || c.chat == nil { + yield(nil, errNilClient) + return + } + input := c.snapshotInput(parts) + span, ctx := startLLMSpan(ctx, "genai.chat.send_message_stream", c.model, c.provider) + + acc := newStreamAccumulator() + var lastErr error + for chunk, err := range c.chat.SendMessageStream(ctx, parts...) { + if err != nil { + lastErr = err + } else { + acc.add(chunk) + } + if !yield(chunk, err) { + break + } + } + finishLLMSpan(span, input, c.config, acc.response(), lastErr) + } +} + +// snapshotInput returns the history at call time plus the new user message, +// taken before genai.Chat mutates History with the turn being sent. +func (c *Chat) snapshotInput(parts []genai.Part) []*genai.Content { + src := c.chat.History(false) + hist := make([]*genai.Content, len(src)) + copy(hist, src) + userParts := make([]*genai.Part, 0, len(parts)) + for i := range parts { + p := parts[i] + userParts = append(userParts, &p) + } + return append(hist, &genai.Content{Parts: userParts, Role: string(genai.RoleUser)}) +} diff --git a/contrib/google.golang.org/genai/client.go b/contrib/google.golang.org/genai/client.go new file mode 100644 index 00000000000..dd2f6cedf28 --- /dev/null +++ b/contrib/google.golang.org/genai/client.go @@ -0,0 +1,67 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace + +import ( + "google.golang.org/genai" +) + +// Client is a tracing wrapper around *genai.Client. Calls on its Models and +// Chats fields produce LLM Observability spans. Use Raw to access the +// underlying *genai.Client for services that are not (yet) instrumented. +type Client struct { + raw *genai.Client + provider string + + // Models wraps the underlying *genai.Client.Models with tracing. + Models *Models + // Chats wraps the underlying *genai.Client.Chats with tracing. + Chats *Chats +} + +// WrapClient returns a tracing wrapper around the given *genai.Client. +// The returned *Client exposes wrapper Models and Chats with the same +// method signatures as the upstream SDK. +// +// Options are reserved for future integration-level configuration; none +// are currently exported, but the variadic form is kept so we can add +// them without a breaking API change. +func WrapClient(c *genai.Client, opts ...Option) *Client { + if c == nil { + return nil + } + cfg := defaults() + for _, opt := range opts { + opt(cfg) + } + provider := backendProvider(c) + tc := &Client{ + raw: c, + provider: provider, + } + tc.Models = &Models{m: c.Models, provider: provider} + tc.Chats = &Chats{c: c.Chats, provider: provider} + return tc +} + +// Raw returns the underlying *genai.Client. +func (c *Client) Raw() *genai.Client { + if c == nil { + return nil + } + return c.raw +} + +func backendProvider(c *genai.Client) string { + switch c.ClientConfig().Backend { + case genai.BackendVertexAI: + return "google_vertexai" + case genai.BackendEnterprise: + return "google_enterprise" + default: + return "google" + } +} diff --git a/contrib/google.golang.org/genai/example_test.go b/contrib/google.golang.org/genai/example_test.go new file mode 100644 index 00000000000..f2ba3bdb5b3 --- /dev/null +++ b/contrib/google.golang.org/genai/example_test.go @@ -0,0 +1,61 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace_test + +import ( + "context" + + "google.golang.org/genai" + + genaitrace "github.com/DataDog/dd-trace-go/contrib/google.golang.org/genai/v2" + + "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" +) + +func Example() { + tracer.Start() + defer tracer.Stop() + + raw, err := genai.NewClient(context.Background(), &genai.ClientConfig{ + APIKey: "your-api-key", + Backend: genai.BackendGeminiAPI, + }) + if err != nil { + panic(err) + } + client := genaitrace.WrapClient(raw) + + resp, err := client.Models.GenerateContent( + context.Background(), + "gemini-2.0-flash", + []*genai.Content{{Role: "user", Parts: []*genai.Part{{Text: "Hello!"}}}}, + nil, + ) + _ = resp + _ = err +} + +func Example_chat() { + tracer.Start() + defer tracer.Stop() + + raw, err := genai.NewClient(context.Background(), &genai.ClientConfig{ + APIKey: "your-api-key", + Backend: genai.BackendGeminiAPI, + }) + if err != nil { + panic(err) + } + client := genaitrace.WrapClient(raw) + + chat, err := client.Chats.Create(context.Background(), "gemini-2.0-flash", nil, nil) + if err != nil { + panic(err) + } + resp, err := chat.SendMessage(context.Background(), genai.Part{Text: "Hello!"}) + _ = resp + _ = err +} diff --git a/contrib/google.golang.org/genai/genai.go b/contrib/google.golang.org/genai/genai.go new file mode 100644 index 00000000000..0021e06ddcf --- /dev/null +++ b/contrib/google.golang.org/genai/genai.go @@ -0,0 +1,22 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +// Package genaitrace provides Datadog LLM Observability tracing for the +// Google GenAI Go SDK (google.golang.org/genai). +// +// Wrap a *genai.Client with [WrapClient] and use the returned *Client in +// place of the original; calls on its Models and Chats fields produce +// LLM Observability spans automatically. +package genaitrace // import "github.com/DataDog/dd-trace-go/contrib/google.golang.org/genai/v2" + +import ( + "github.com/DataDog/dd-trace-go/v2/instrumentation" +) + +var instr *instrumentation.Instrumentation + +func init() { + instr = instrumentation.Load(instrumentation.PackageGoogleAPIsGoGenAI) +} diff --git a/contrib/google.golang.org/genai/genai_test.go b/contrib/google.golang.org/genai/genai_test.go new file mode 100644 index 00000000000..dd03158d387 --- /dev/null +++ b/contrib/google.golang.org/genai/genai_test.go @@ -0,0 +1,326 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/genai" + + "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer" + "github.com/DataDog/dd-trace-go/v2/ddtrace/x/llmobstest" + "github.com/DataDog/dd-trace-go/v2/ddtrace/x/tracertest" +) + +func testTracer(t *testing.T) *llmobstest.Collector { + t.Helper() + coll := llmobstest.New(t) + _, _, err := tracertest.Bootstrap(t, + tracer.WithLLMObsEnabled(true), + tracer.WithLLMObsMLApp("test-genai-app"), + tracer.WithLogStartup(false), + coll.TracerOption(), + ) + require.NoError(t, err) + return coll +} + +// mockServer serves any path with the same canned JSON payload and supports +// SSE streaming when ?alt=sse is present. +func mockServer(t *testing.T, payload any, sseChunks []any) *httptest.Server { + t.Helper() + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Query().Get("alt") == "sse" || strings.Contains(r.URL.RawQuery, "alt=sse") { + w.Header().Set("Content-Type", "text/event-stream") + w.WriteHeader(http.StatusOK) + for _, c := range sseChunks { + b, _ := json.Marshal(c) + _, _ = w.Write([]byte("data: ")) + _, _ = w.Write(b) + _, _ = w.Write([]byte("\n\n")) + if f, ok := w.(http.Flusher); ok { + f.Flush() + } + } + return + } + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(payload) + })) +} + +func newTestClient(t *testing.T, baseURL string) *genai.Client { + t.Helper() + c, err := genai.NewClient(context.Background(), &genai.ClientConfig{ + APIKey: "test-key", + Backend: genai.BackendGeminiAPI, + HTTPOptions: genai.HTTPOptions{ + BaseURL: baseURL, + }, + }) + require.NoError(t, err) + return c +} + +func TestGenerateContent(t *testing.T) { + tt := testTracer(t) + + payload := map[string]any{ + "candidates": []map[string]any{ + { + "content": map[string]any{ + "role": "model", + "parts": []map[string]any{{"text": "Hello world!"}}, + }, + "finishReason": "STOP", + "index": 0, + }, + }, + "usageMetadata": map[string]any{ + "promptTokenCount": 7, + "candidatesTokenCount": 3, + "totalTokenCount": 10, + }, + "modelVersion": "gemini-2.0-flash", + } + srv := mockServer(t, payload, nil) + defer srv.Close() + + client := WrapClient(newTestClient(t, srv.URL)) + + resp, err := client.Models.GenerateContent( + context.Background(), + "gemini-2.0-flash", + []*genai.Content{{Role: "user", Parts: []*genai.Part{{Text: "hi"}}}}, + nil, + ) + require.NoError(t, err) + require.NotNil(t, resp) + assert.Equal(t, "Hello world!", resp.Text()) + + tracer.Flush() + spans := tt.Spans() + require.Len(t, spans, 1) + + s := spans[0] + assert.Equal(t, "genai.generate_content", s.Name) + assert.Equal(t, "llm", s.Meta["span.kind"]) + assert.Equal(t, "gemini-2.0-flash", s.Meta["model_name"]) + assert.Equal(t, "google", s.Meta["model_provider"]) + + require.Contains(t, s.Metrics, "input_tokens") + require.Contains(t, s.Metrics, "output_tokens") + require.Contains(t, s.Metrics, "total_tokens") + assert.EqualValues(t, 7, s.Metrics["input_tokens"]) + assert.EqualValues(t, 3, s.Metrics["output_tokens"]) + assert.EqualValues(t, 10, s.Metrics["total_tokens"]) + + require.Contains(t, s.Meta, "input") + require.Contains(t, s.Meta, "output") + inputJSON, _ := json.Marshal(s.Meta["input"]) + outputJSON, _ := json.Marshal(s.Meta["output"]) + assert.Contains(t, string(inputJSON), "hi") + assert.Contains(t, string(inputJSON), "user") + assert.Contains(t, string(outputJSON), "Hello world!") + assert.Contains(t, string(outputJSON), "assistant") +} + +func TestGenerateContentStream(t *testing.T) { + tt := testTracer(t) + + chunks := []any{ + map[string]any{ + "candidates": []map[string]any{{ + "content": map[string]any{"role": "model", "parts": []map[string]any{{"text": "Hello "}}}, + "index": 0, + }}, + }, + map[string]any{ + "candidates": []map[string]any{{ + "content": map[string]any{"role": "model", "parts": []map[string]any{{"text": "world!"}}}, + "finishReason": "STOP", + "index": 0, + }}, + "usageMetadata": map[string]any{ + "promptTokenCount": 2, + "candidatesTokenCount": 2, + "totalTokenCount": 4, + }, + }, + } + srv := mockServer(t, nil, chunks) + defer srv.Close() + + client := WrapClient(newTestClient(t, srv.URL)) + + var collected strings.Builder + for chunk, err := range client.Models.GenerateContentStream( + context.Background(), + "gemini-2.0-flash", + []*genai.Content{{Role: "user", Parts: []*genai.Part{{Text: "hi"}}}}, + nil, + ) { + require.NoError(t, err) + if chunk != nil { + collected.WriteString(chunk.Text()) + } + } + assert.Equal(t, "Hello world!", collected.String()) + + tracer.Flush() + spans := tt.Spans() + require.Len(t, spans, 1) + s := spans[0] + assert.Equal(t, "genai.generate_content_stream", s.Name) + outputJSON, _ := json.Marshal(s.Meta["output"]) + assert.Contains(t, string(outputJSON), "Hello world!") + assert.EqualValues(t, 4, s.Metrics["total_tokens"]) +} + +func TestEmbedContent(t *testing.T) { + tt := testTracer(t) + + payload := map[string]any{ + "embeddings": []map[string]any{ + {"values": []float32{0.1, 0.2, 0.3}}, + }, + } + srv := mockServer(t, payload, nil) + defer srv.Close() + + client := WrapClient(newTestClient(t, srv.URL)) + + resp, err := client.Models.EmbedContent( + context.Background(), + "text-embedding-004", + []*genai.Content{{Parts: []*genai.Part{{Text: "embed me"}}}}, + nil, + ) + require.NoError(t, err) + require.NotNil(t, resp) + require.Len(t, resp.Embeddings, 1) + assert.Len(t, resp.Embeddings[0].Values, 3) + + tracer.Flush() + spans := tt.Spans() + require.Len(t, spans, 1) + s := spans[0] + assert.Equal(t, "genai.embed_content", s.Name) + assert.Equal(t, "embedding", s.Meta["span.kind"]) + assert.Equal(t, "text-embedding-004", s.Meta["model_name"]) + inputJSON, _ := json.Marshal(s.Meta["input"]) + outputJSON, _ := json.Marshal(s.Meta["output"]) + assert.Contains(t, string(inputJSON), "embed me") + assert.Contains(t, string(outputJSON), "3 floats") +} + +func TestChatSendMessage(t *testing.T) { + tt := testTracer(t) + + payload := map[string]any{ + "candidates": []map[string]any{ + { + "content": map[string]any{ + "role": "model", + "parts": []map[string]any{{"text": "Hi back!"}}, + }, + "finishReason": "STOP", + "index": 0, + }, + }, + "usageMetadata": map[string]any{ + "promptTokenCount": 5, + "candidatesTokenCount": 2, + "totalTokenCount": 7, + }, + } + srv := mockServer(t, payload, nil) + defer srv.Close() + + client := WrapClient(newTestClient(t, srv.URL)) + + chat, err := client.Chats.Create(context.Background(), "gemini-2.0-flash", nil, []*genai.Content{ + {Role: "user", Parts: []*genai.Part{{Text: "previous question"}}}, + {Role: "model", Parts: []*genai.Part{{Text: "previous answer"}}}, + }) + require.NoError(t, err) + + resp, err := chat.SendMessage(context.Background(), genai.Part{Text: "Hello!"}) + require.NoError(t, err) + assert.Equal(t, "Hi back!", resp.Text()) + + // Second send: ensures we snapshot history *before* the call, since + // genai.Chat appends the just-sent turn to History on success. + resp, err = chat.SendMessage(context.Background(), genai.Part{Text: "Follow up?"}) + require.NoError(t, err) + assert.Equal(t, "Hi back!", resp.Text()) + + tracer.Flush() + spans := tt.Spans() + require.Len(t, spans, 2) + + for _, s := range spans { + assert.Equal(t, "genai.chat.send_message", s.Name) + assert.Equal(t, "gemini-2.0-flash", s.Meta["model_name"]) + } + + // First-call span: history + first user message only. The assistant + // reply for this turn must NOT appear in this turn's recorded input. + inputJSON, _ := json.Marshal(spans[0].Meta["input"]) + in := string(inputJSON) + assert.Contains(t, in, "previous question") + assert.Contains(t, in, "previous answer") + assert.Contains(t, in, "Hello!") + assert.NotContains(t, in, "Follow up?") + assert.Equal(t, 0, strings.Count(in, "Hi back!")) + assert.Equal(t, 1, strings.Count(in, "Hello!")) + + // Second-call span: includes the first completed turn (user + assistant) + // plus the new user message, with no duplicated user content. + inputJSON2, _ := json.Marshal(spans[1].Meta["input"]) + in2 := string(inputJSON2) + assert.Contains(t, in2, "Hello!") + assert.Contains(t, in2, "Follow up?") + assert.Equal(t, 1, strings.Count(in2, "Hello!")) + assert.Equal(t, 1, strings.Count(in2, "Follow up?")) + assert.Equal(t, 1, strings.Count(in2, "Hi back!")) + + outputJSON, _ := json.Marshal(spans[0].Meta["output"]) + assert.Contains(t, string(outputJSON), "Hi back!") + assert.EqualValues(t, 7, spans[0].Metrics["total_tokens"]) +} + +func TestGenerateContentError(t *testing.T) { + tt := testTracer(t) + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(`{"error":{"message":"boom"}}`)) + })) + defer srv.Close() + + client := WrapClient(newTestClient(t, srv.URL)) + _, err := client.Models.GenerateContent( + context.Background(), + "gemini-2.0-flash", + []*genai.Content{{Role: "user", Parts: []*genai.Part{{Text: "hi"}}}}, + nil, + ) + require.Error(t, err) + + tracer.Flush() + spans := tt.Spans() + require.Len(t, spans, 1) + s := spans[0] + assert.Contains(t, s.Meta, "error.message") +} diff --git a/contrib/google.golang.org/genai/go.mod b/contrib/google.golang.org/genai/go.mod new file mode 100644 index 00000000000..30bb124d6ed --- /dev/null +++ b/contrib/google.golang.org/genai/go.mod @@ -0,0 +1,95 @@ +module github.com/DataDog/dd-trace-go/contrib/google.golang.org/genai/v2 + +go 1.25.0 + +require ( + github.com/DataDog/dd-trace-go/v2 v2.10.0-dev + github.com/stretchr/testify v1.11.1 + google.golang.org/genai v1.62.0 +) + +require ( + cloud.google.com/go v0.116.0 // indirect + cloud.google.com/go/auth v0.9.3 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/obfuscate v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/opentelemetry-mapping-go/otlp/attributes v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/proto v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/trace v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/trace/log v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/trace/stats v0.79.0 // indirect + github.com/DataDog/datadog-agent/pkg/trace/traceutil v0.79.0 // indirect + github.com/DataDog/datadog-go/v5 v5.8.3 // indirect + github.com/DataDog/go-libddwaf/v5 v5.0.0 // indirect + github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20260217080614-b0f4edc38a6d // indirect + github.com/DataDog/go-sqllexer v0.2.1 // indirect + github.com/DataDog/go-tuf v1.1.1-0.5.2 // indirect + github.com/DataDog/sketches-go v1.4.8 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/s2a-go v0.1.8 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/hashicorp/go-version v1.9.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.18.6 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/linkdata/deadlock v0.5.5 // indirect + github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88 // indirect + github.com/minio/simdjson-go v0.4.5 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/outcaste-io/ristretto v0.2.3 // indirect + github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6 // indirect + github.com/philhofer/fwd v1.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.10.0 // indirect + github.com/shirou/gopsutil/v4 v4.26.3 // indirect + github.com/tinylib/msgp v1.6.3 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect + github.com/trailofbits/go-mutexasserts v0.0.0-20250514102930-c1f3d2e37561 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/collector/component v1.56.0 // indirect + go.opentelemetry.io/collector/featuregate v1.56.0 // indirect + go.opentelemetry.io/collector/pdata v1.56.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.150.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.52.0 // indirect + golang.org/x/exp v0.0.0-20260209203927-2842357ff358 // indirect + golang.org/x/mod v0.35.0 // indirect + golang.org/x/net v0.55.0 // indirect + golang.org/x/sys v0.45.0 // indirect + golang.org/x/text v0.37.0 // indirect + golang.org/x/time v0.15.0 // indirect + golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect + google.golang.org/grpc v1.80.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/DataDog/dd-trace-go/v2 => ../../.. diff --git a/contrib/google.golang.org/genai/go.sum b/contrib/google.golang.org/genai/go.sum new file mode 100644 index 00000000000..df218ea3808 --- /dev/null +++ b/contrib/google.golang.org/genai/go.sum @@ -0,0 +1,345 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U= +cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.79.0 h1:VZlYzVCzCsY3TsEdDCFHklzL2k2C3OeQvgDhU2gllg0= +github.com/DataDog/datadog-agent/comp/core/tagger/origindetection v0.79.0/go.mod h1:dz3fkTBxANLLLigy9KQ5jhNZ28nA4dI9AxuLoGrmR0o= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.79.0 h1:PeYLm/gZQM7iKXOG4NgbKo6ZfpG73/+f8TSzmCUtA6g= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.79.0/go.mod h1:1Us875zf/kICMHUcxHE5HNo1rCQlvLBmo1tfZEuzJVw= +github.com/DataDog/datadog-agent/pkg/opentelemetry-mapping-go/otlp/attributes v0.79.0 h1:J4rWJpsGnGAXUtcdr9Vq5cMN2ccrf+VhUJnHuRuc1zg= +github.com/DataDog/datadog-agent/pkg/opentelemetry-mapping-go/otlp/attributes v0.79.0/go.mod h1:GqMFabP1nLfle3seDNJYcj/wfCSKbAcUGFkkEasd7JE= +github.com/DataDog/datadog-agent/pkg/proto v0.79.0 h1:8QbV9DFIWQn16eUHJ6WGxcdnk+0zKcVD3Oug/1Pz8q4= +github.com/DataDog/datadog-agent/pkg/proto v0.79.0/go.mod h1:cHqU71Z8zkEt79uOK8dz534jbpDlXQyHgoLQRuaHpMw= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.79.0 h1:7oCAk0/aLP+0xJqw+xSDb0WN7g9Yramx6uOltgICplo= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.79.0/go.mod h1:kFG+DDnQHvaQ1EUlhKmVRny7pYXmWhpQVWCM48uWP8I= +github.com/DataDog/datadog-agent/pkg/trace v0.79.0 h1:gvqATgSGFbIWTm+v7TapIHvR8rDOJvE7eZUgxx6Bvhk= +github.com/DataDog/datadog-agent/pkg/trace v0.79.0/go.mod h1:3oEA+txSBo1/jH7wIi5GhPRuMki7PSl5r/YM8cubtxs= +github.com/DataDog/datadog-agent/pkg/trace/log v0.79.0 h1:MQACMCllIqhkq1Z45WU4ymKQBjVG2zPWpQ1gerf8CkM= +github.com/DataDog/datadog-agent/pkg/trace/log v0.79.0/go.mod h1:7JxAuxV2tRfr9Si8C9W+dF5qFU0x0K1hi07nrn9xIAU= +github.com/DataDog/datadog-agent/pkg/trace/stats v0.79.0 h1:MUJOjHKp0xt08CWoiZwwLhEyW2+9KspcjOZMLclmGT8= +github.com/DataDog/datadog-agent/pkg/trace/stats v0.79.0/go.mod h1:/pNMg3r6LPDz1PBNK60/3FqhKPh6J19eNO2newT6bwU= +github.com/DataDog/datadog-agent/pkg/trace/traceutil v0.79.0 h1:NM/Fw/ku/Hjj26l8Y2Jtojd7BEI+C7sb5jikAPBX6lE= +github.com/DataDog/datadog-agent/pkg/trace/traceutil v0.79.0/go.mod h1:+LtS5cUALIDB7lT3G3w/pfpHSgxPQ/7z1Ub2UT/BW5s= +github.com/DataDog/datadog-go/v5 v5.8.3 h1:s58CUJ9s8lezjhTNJO/SxkPBv2qZjS3ktpRSqGF5n0s= +github.com/DataDog/datadog-go/v5 v5.8.3/go.mod h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw= +github.com/DataDog/go-libddwaf/v5 v5.0.0 h1:uPQfIVPH9T8jLSplAdfETAHwL3iRLabP6JxRTH8NL7Y= +github.com/DataDog/go-libddwaf/v5 v5.0.0/go.mod h1:/UzdsIsO8qk8fmbqNnk6Na7MsaNvU2R7SlBRHEgSIOQ= +github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20260217080614-b0f4edc38a6d h1:cH9Bm0tJ8FEQbA4FRi0iRm7Zr/5Lata/Or31c+Dth0E= +github.com/DataDog/go-runtime-metrics-internal v0.0.4-0.20260217080614-b0f4edc38a6d/go.mod h1:yDuvU+Ak1TKwgd4K8DNcpJmUrrK8ONLkBMGNAppmBRk= +github.com/DataDog/go-sqllexer v0.2.1 h1:al1RMRTxPoAa1P/RTu7D5yVXC6wCLwTRYLVAVH5MLjQ= +github.com/DataDog/go-sqllexer v0.2.1/go.mod h1:3xTFXBU69vUikYpESggScvC0RKYA7ZIdVrIkLwUOWdE= +github.com/DataDog/go-tuf v1.1.1-0.5.2 h1:YWvghV4ZvrQsPcUw8IOUMSDpqc3W5ruOIC+KJxPknv0= +github.com/DataDog/go-tuf v1.1.1-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= +github.com/DataDog/sketches-go v1.4.8 h1:pFk9BNn+Rzv8IMIoPUttoOpOr3bJOqU3P6EP5wK+Lv8= +github.com/DataDog/sketches-go v1.4.8/go.mod h1:a/wjRUqzqtGS8qRHRPDCs4EAQfmvPDZGDlMIF5mxXOE= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs= +github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= +github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= +github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= +github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/linkdata/deadlock v0.5.5 h1:d6O+rzEqasSfamGDA8u7bjtaq7hOX8Ha4Zn36Wxrkvo= +github.com/linkdata/deadlock v0.5.5/go.mod h1:tXb28stzAD3trzEEK0UJWC+rZKuobCoPktPYzebb1u0= +github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88 h1:PTw+yKnXcOFCR6+8hHTyWBeQ/P4Nb7dd4/0ohEcWQuM= +github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/minio/simdjson-go v0.4.5 h1:r4IQwjRGmWCQ2VeMc7fGiilu1z5du0gJ/I/FsKwgo5A= +github.com/minio/simdjson-go v0.4.5/go.mod h1:eoNz0DcLQRyEDeaPr4Ru6JpjlZPzbA0IodxVJk8lO8E= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= +github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6 h1:rh2lKw/P/EqHa724vYH2+VVQ1YnW4u6EOXl0PMAovZE= +github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg= +github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= +github.com/richardartoul/molecule v1.0.1-0.20240531184615-7ca0df43c0b3 h1:4+LEVOB87y175cLJC/mbsgKmoDOjrBldtXvioEy96WY= +github.com/richardartoul/molecule v1.0.1-0.20240531184615-7ca0df43c0b3/go.mod h1:vl5+MqJ1nBINuSsUI2mGgH79UweUT/B5Fy8857PqyyI= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/secure-systems-lab/go-securesystemslib v0.10.0 h1:l+H5ErcW0PAehBNrBxoGv1jjNpGYdZ9RcheFkB2WI14= +github.com/secure-systems-lab/go-securesystemslib v0.10.0/go.mod h1:MRKONWmRoFzPNQ9USRF9i1mc7MvAVvF1LlW8X5VWDvk= +github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= +github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s= +github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= +github.com/trailofbits/go-mutexasserts v0.0.0-20250514102930-c1f3d2e37561 h1:qqa3P9AtNn6RMe90l/lxd3eJWnIRxjI4eb5Rx8xqCLA= +github.com/trailofbits/go-mutexasserts v0.0.0-20250514102930-c1f3d2e37561/go.mod h1:GA3+Mq3kt3tYAfM0WZCu7ofy+GW9PuGysHfhr+6JX7s= +github.com/vmihailenco/msgpack/v4 v4.3.13 h1:A2wsiTbvp63ilDaWmsk2wjx6xZdxQOvpiNlKBGKKXKI= +github.com/vmihailenco/msgpack/v4 v4.3.13/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/collector/component v1.56.0 h1:fOCs36Dxg95w2RQCVI2i5IsHc5IbZ99vmbipK9FM7pQ= +go.opentelemetry.io/collector/component v1.56.0/go.mod h1:MkAjcSc2T0BiYf/uARZdTlfnxBB9BwmvY6v08D+qeY4= +go.opentelemetry.io/collector/component/componenttest v0.150.0 h1:pT7avT/Pfn8tAOOlmFWgtOaGvXY0nxSwrivnhOl/LH0= +go.opentelemetry.io/collector/component/componenttest v0.150.0/go.mod h1:D+7mfbcZ/TfneQRZNtVwH+/YKQdalc1joa9NhH1BGPk= +go.opentelemetry.io/collector/featuregate v1.56.0 h1:NjcbOZkdCSXddAJmFLdO+pv1gmAgrU6sC5PBga2KlKI= +go.opentelemetry.io/collector/featuregate v1.56.0/go.mod h1:4ga1QBMPEejXXmpyJS8lmaRpknJ3Lb9Bvk6e420bUFU= +go.opentelemetry.io/collector/internal/testutil v0.150.0 h1:J4PLQGPfbLVaL5eI1aMc0m0TMixV9wzBhNhoHU00J0I= +go.opentelemetry.io/collector/internal/testutil v0.150.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE= +go.opentelemetry.io/collector/pdata v1.56.0 h1:W+QAfN2Iz8SNss1T5JNzRWFnw+7oP1vXBQH9ZuOJkXY= +go.opentelemetry.io/collector/pdata v1.56.0/go.mod h1:usR9utboXufbD1rp1oJy+3smQXXpZ+CsI3WN7QsiOs0= +go.opentelemetry.io/collector/pdata/pprofile v0.150.0 h1:Ae+FxmYXDdcqeLqIAdNSO3YGxco7RS2mIMTdjvavfso= +go.opentelemetry.io/collector/pdata/pprofile v0.150.0/go.mod h1:tEBeGysY/LpIh39NLoQQl3qmUBOF9wyH5p/fmn7smzM= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= +go.opentelemetry.io/proto/slim/otlp v1.10.0 h1:iR97Vs/ZDR+y9TfuP9b1XBtdPWeC+OMslIBmhcLU7jM= +go.opentelemetry.io/proto/slim/otlp v1.10.0/go.mod h1:lV9250stpjYLPNA5viFabIgP2QlUGRT1GdTgAf8SIUk= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0 h1:RUF5rO0hAlgiJt1fzQVzcVs3vZVNHIcMLgOgG4rWNcQ= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0/go.mod h1:I89cynRj8y+383o7tEQVg2SVA6SRgDVIouWPUVXjx0U= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0 h1:CQvJSldHRUN6Z8jsUeYv8J0lXRvygALXIzsmAeCcZE0= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0/go.mod h1:xSQ+mEfJe/GjK1LXEyVOoSI1N9JV9ZI923X5kup43W4= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= +golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20260209203927-2842357ff358 h1:kpfSV7uLwKJbFSEgNhWzGSL47NDSF/5pYYQw1V0ub6c= +golang.org/x/exp v0.0.0-20260209203927-2842357ff358/go.mod h1:R3t0oliuryB5eenPWl3rrQxwnNM3WTwnsRZZiXLAAW8= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genai v1.62.0 h1:PaBju84orf4Vbcc6OfHe4vxhxhjwulKTgOpEc3iIc00= +google.golang.org/genai v1.62.0/go.mod h1:mDdPDFXo1Ats7f1WXVyZgWb/CkMzFWTWJruIMy7hGIU= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/contrib/google.golang.org/genai/models.go b/contrib/google.golang.org/genai/models.go new file mode 100644 index 00000000000..cc0621a27cb --- /dev/null +++ b/contrib/google.golang.org/genai/models.go @@ -0,0 +1,79 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace + +import ( + "context" + "iter" + + "google.golang.org/genai" + + "github.com/DataDog/dd-trace-go/v2/instrumentation" + "github.com/DataDog/dd-trace-go/v2/llmobs" +) + +const integration = string(instrumentation.PackageGoogleAPIsGoGenAI) + +// Models wraps *genai.Client.Models with LLM Observability tracing. +type Models struct { + m *genai.Models + provider string +} + +// GenerateContent generates content from the model and emits an LLM span. +func (m *Models) GenerateContent(ctx context.Context, model string, contents []*genai.Content, config *genai.GenerateContentConfig) (*genai.GenerateContentResponse, error) { + if m == nil || m.m == nil { + return nil, errNilClient + } + span, ctx := startLLMSpan(ctx, "genai.generate_content", model, m.provider) + + resp, err := m.m.GenerateContent(ctx, model, contents, config) + finishLLMSpan(span, contents, config, resp, err) + return resp, err +} + +// GenerateContentStream streams content from the model and emits an LLM span +// covering the entire stream. The span is finished when the returned iterator +// is fully consumed (or the caller stops iterating). +func (m *Models) GenerateContentStream(ctx context.Context, model string, contents []*genai.Content, config *genai.GenerateContentConfig) iter.Seq2[*genai.GenerateContentResponse, error] { + return func(yield func(*genai.GenerateContentResponse, error) bool) { + if m == nil || m.m == nil { + yield(nil, errNilClient) + return + } + span, ctx := startLLMSpan(ctx, "genai.generate_content_stream", model, m.provider) + + acc := newStreamAccumulator() + var lastErr error + for chunk, err := range m.m.GenerateContentStream(ctx, model, contents, config) { + if err != nil { + lastErr = err + } else { + acc.add(chunk) + } + if !yield(chunk, err) { + break + } + } + finishLLMSpan(span, contents, config, acc.response(), lastErr) + } +} + +// EmbedContent generates an embedding from the model and emits an embedding span. +func (m *Models) EmbedContent(ctx context.Context, model string, contents []*genai.Content, config *genai.EmbedContentConfig) (*genai.EmbedContentResponse, error) { + if m == nil || m.m == nil { + return nil, errNilClient + } + span, ctx := llmobs.StartEmbeddingSpan(ctx, "genai.embed_content", + llmobs.WithModelName(model), + llmobs.WithModelProvider(m.provider), + llmobs.WithIntegration(integration), + ) + + resp, err := m.m.EmbedContent(ctx, model, contents, config) + finishEmbeddingSpan(span, contents, resp, err) + return resp, err +} diff --git a/contrib/google.golang.org/genai/option.go b/contrib/google.golang.org/genai/option.go new file mode 100644 index 00000000000..4400b5ff24e --- /dev/null +++ b/contrib/google.golang.org/genai/option.go @@ -0,0 +1,17 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace + +// config holds integration-level configuration for the wrapper. Individual +// options are functional and are applied by [WrapClient]. +type config struct{} + +// Option customizes the behavior of the tracing wrapper returned by [WrapClient]. +type Option func(*config) + +func defaults() *config { + return &config{} +} diff --git a/contrib/google.golang.org/genai/span.go b/contrib/google.golang.org/genai/span.go new file mode 100644 index 00000000000..952bd45fc78 --- /dev/null +++ b/contrib/google.golang.org/genai/span.go @@ -0,0 +1,217 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace + +import ( + "context" + "errors" + "strings" + + "google.golang.org/genai" + + "github.com/DataDog/dd-trace-go/v2/llmobs" +) + +var errNilClient = errors.New("genaitrace: wrapped client is nil") + +func startLLMSpan(ctx context.Context, name, model, provider string) (*llmobs.LLMSpan, context.Context) { + return llmobs.StartLLMSpan(ctx, name, + llmobs.WithModelName(model), + llmobs.WithModelProvider(provider), + llmobs.WithIntegration(integration), + ) +} + +// finishLLMSpan annotates and finishes an LLM span with input/output messages, +// generation config metadata, token usage metrics and any error. +func finishLLMSpan(span *llmobs.LLMSpan, contents []*genai.Content, config *genai.GenerateContentConfig, resp *genai.GenerateContentResponse, err error) { + annotateLLMIO(span, contents, config, resp) + + if err != nil { + span.Finish(llmobs.WithError(err)) + return + } + span.Finish() +} + +func annotateLLMIO(span *llmobs.LLMSpan, contents []*genai.Content, config *genai.GenerateContentConfig, resp *genai.GenerateContentResponse) { + input := contentsToMessages(contents, "user") + if config != nil && config.SystemInstruction != nil { + sys := contentsToMessages([]*genai.Content{config.SystemInstruction}, "system") + input = append(sys, input...) + } + + var output []llmobs.LLMMessage + if resp != nil { + for _, cand := range resp.Candidates { + if cand == nil || cand.Content == nil { + continue + } + output = append(output, contentToMessage(cand.Content, "assistant")) + } + } + + opts := []llmobs.AnnotateOption{} + if meta := generationMetadata(config); len(meta) > 0 { + opts = append(opts, llmobs.WithAnnotatedMetadata(meta)) + } + if metrics := usageMetrics(resp); len(metrics) > 0 { + opts = append(opts, llmobs.WithAnnotatedMetrics(metrics)) + } + span.AnnotateLLMIO(input, output, opts...) +} + +func generationMetadata(config *genai.GenerateContentConfig) map[string]any { + if config == nil { + return nil + } + meta := map[string]any{} + if config.Temperature != nil { + meta["temperature"] = *config.Temperature + } + if config.TopP != nil { + meta["top_p"] = *config.TopP + } + if config.TopK != nil { + meta["top_k"] = *config.TopK + } + if config.MaxOutputTokens != 0 { + meta["max_output_tokens"] = config.MaxOutputTokens + } + if len(config.StopSequences) > 0 { + meta["stop_sequences"] = config.StopSequences + } + if len(meta) == 0 { + return nil + } + return meta +} + +func usageMetrics(resp *genai.GenerateContentResponse) map[string]float64 { + if resp == nil || resp.UsageMetadata == nil { + return nil + } + u := resp.UsageMetadata + metrics := map[string]float64{} + if u.PromptTokenCount != 0 { + metrics[llmobs.MetricKeyInputTokens] = float64(u.PromptTokenCount) + } + if u.CandidatesTokenCount != 0 { + metrics[llmobs.MetricKeyOutputTokens] = float64(u.CandidatesTokenCount) + } + if u.TotalTokenCount != 0 { + metrics[llmobs.MetricKeyTotalTokens] = float64(u.TotalTokenCount) + } + if u.CachedContentTokenCount != 0 { + metrics[llmobs.MetricKeyCacheReadInputTokens] = float64(u.CachedContentTokenCount) + } + if u.ThoughtsTokenCount != 0 { + metrics[llmobs.MetricKeyReasoningOutputTokens] = float64(u.ThoughtsTokenCount) + } + if len(metrics) == 0 { + return nil + } + return metrics +} + +func contentsToMessages(contents []*genai.Content, defaultRole string) []llmobs.LLMMessage { + out := make([]llmobs.LLMMessage, 0, len(contents)) + for _, c := range contents { + if c == nil { + continue + } + out = append(out, contentToMessage(c, defaultRole)) + } + return out +} + +func contentToMessage(c *genai.Content, defaultRole string) llmobs.LLMMessage { + role := c.Role + if role == "" { + role = defaultRole + } else if role == string(genai.RoleModel) { + role = "assistant" + } + msg := llmobs.LLMMessage{Role: role} + + var textParts []string + for _, p := range c.Parts { + if p == nil { + continue + } + if p.Text != "" { + textParts = append(textParts, p.Text) + } + if fc := p.FunctionCall; fc != nil { + args, _ := jsonRaw(fc.Args) + msg.ToolCalls = append(msg.ToolCalls, llmobs.ToolCall{ + Name: fc.Name, + Arguments: args, + ToolID: fc.ID, + Type: "function", + }) + } + if fr := p.FunctionResponse; fr != nil { + msg.ToolResults = append(msg.ToolResults, llmobs.ToolResult{ + Name: fr.Name, + Result: fr.Response, + ToolID: fr.ID, + Type: "function", + }) + } + } + msg.Content = strings.Join(textParts, "") + return msg +} + +func finishEmbeddingSpan(span *llmobs.EmbeddingSpan, contents []*genai.Content, resp *genai.EmbedContentResponse, err error) { + docs := embedDocs(contents) + output := embedSummary(resp) + span.AnnotateEmbeddingIO(docs, output) + + if err != nil { + span.Finish(llmobs.WithError(err)) + return + } + span.Finish() +} + +func embedDocs(contents []*genai.Content) []llmobs.EmbeddedDocument { + out := make([]llmobs.EmbeddedDocument, 0, len(contents)) + for _, c := range contents { + if c == nil { + continue + } + var parts []string + for _, p := range c.Parts { + if p != nil && p.Text != "" { + parts = append(parts, p.Text) + } + } + out = append(out, llmobs.EmbeddedDocument{Text: strings.Join(parts, "")}) + } + return out +} + +func embedSummary(resp *genai.EmbedContentResponse) string { + if resp == nil || len(resp.Embeddings) == 0 { + return "" + } + var b strings.Builder + for i, e := range resp.Embeddings { + if i > 0 { + b.WriteString(", ") + } + if e == nil { + b.WriteString("[]") + continue + } + b.WriteString("[") + b.WriteString(itoa(len(e.Values))) + b.WriteString(" floats]") + } + return b.String() +} diff --git a/contrib/google.golang.org/genai/stream.go b/contrib/google.golang.org/genai/stream.go new file mode 100644 index 00000000000..168d4a92b91 --- /dev/null +++ b/contrib/google.golang.org/genai/stream.go @@ -0,0 +1,112 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +package genaitrace + +import ( + "encoding/json" + "strconv" + "strings" + + "google.golang.org/genai" +) + +// streamAccumulator coalesces streamed GenerateContentResponse chunks into a +// single synthetic response so the span can be annotated with the full text, +// final usage metadata and finish reason. +type streamAccumulator struct { + texts map[int32]*strings.Builder + candidates map[int32]*genai.Candidate + indexOrder []int32 + usage *genai.GenerateContentResponseUsageMetadata + modelVersion string + responseID string +} + +func newStreamAccumulator() *streamAccumulator { + return &streamAccumulator{ + texts: map[int32]*strings.Builder{}, + candidates: map[int32]*genai.Candidate{}, + } +} + +func (s *streamAccumulator) add(chunk *genai.GenerateContentResponse) { + if chunk == nil { + return + } + if chunk.UsageMetadata != nil { + s.usage = chunk.UsageMetadata + } + if chunk.ModelVersion != "" { + s.modelVersion = chunk.ModelVersion + } + if chunk.ResponseID != "" { + s.responseID = chunk.ResponseID + } + for _, cand := range chunk.Candidates { + if cand == nil { + continue + } + idx := cand.Index + if _, seen := s.candidates[idx]; !seen { + s.indexOrder = append(s.indexOrder, idx) + s.texts[idx] = &strings.Builder{} + } + // Keep the latest candidate to capture finish reason / safety ratings. + s.candidates[idx] = cand + if cand.Content != nil { + for _, p := range cand.Content.Parts { + if p != nil && p.Text != "" { + s.texts[idx].WriteString(p.Text) + } + } + } + } +} + +func (s *streamAccumulator) response() *genai.GenerateContentResponse { + if len(s.indexOrder) == 0 && s.usage == nil { + return nil + } + resp := &genai.GenerateContentResponse{ + UsageMetadata: s.usage, + ModelVersion: s.modelVersion, + ResponseID: s.responseID, + } + for _, idx := range s.indexOrder { + cand := s.candidates[idx] + role := string(genai.RoleModel) + if cand.Content != nil && cand.Content.Role != "" { + role = cand.Content.Role + } + merged := &genai.Candidate{ + FinishReason: cand.FinishReason, + FinishMessage: cand.FinishMessage, + Index: cand.Index, + Content: &genai.Content{ + Role: role, + Parts: []*genai.Part{{Text: s.texts[idx].String()}}, + }, + } + resp.Candidates = append(resp.Candidates, merged) + } + return resp +} + +// jsonRaw marshals v to json.RawMessage; on error it returns nil. +func jsonRaw(v any) (json.RawMessage, error) { + if v == nil { + return nil, nil + } + b, err := json.Marshal(v) + if err != nil { + return nil, err + } + return b, nil +} + +func itoa(n int) string { + return strconv.Itoa(n) +} diff --git a/ddtrace/tracer/option.go b/ddtrace/tracer/option.go index 66f3796a2db..7fb4fbf4c0d 100644 --- a/ddtrace/tracer/option.go +++ b/ddtrace/tracer/option.go @@ -86,6 +86,7 @@ var contribIntegrations = map[string]struct { "github.com/gofiber/fiber/v2": {"Fiber", false}, "github.com/gomodule/redigo": {"Redigo", false}, "google.golang.org/api": {"Google API", false}, + "google.golang.org/genai": {"Google GenAI Go SDK", false}, "google.golang.org/grpc": {"gRPC", false}, "github.com/gorilla/mux": {"Gorilla Mux", false}, "gorm.io/gorm.v1": {"Gorm v1", false}, diff --git a/ddtrace/tracer/option_test.go b/ddtrace/tracer/option_test.go index 7c96635aba0..eb8f033fcd4 100644 --- a/ddtrace/tracer/option_test.go +++ b/ddtrace/tracer/option_test.go @@ -388,7 +388,7 @@ func TestAgentIntegration(t *testing.T) { defer clearIntegrationsForTests() cfg.loadContribIntegrations(nil) - assert.Equal(t, 58, len(cfg.integrations)) + assert.Equal(t, 59, len(cfg.integrations)) for integrationName, v := range cfg.integrations { assert.False(t, v.Instrumented, "integrationName=%s", integrationName) } diff --git a/go.work b/go.work index 97a6d2485f3..e1c14bb3d62 100644 --- a/go.work +++ b/go.work @@ -36,6 +36,7 @@ use ( ./contrib/gomodule/redigo ./contrib/google.golang.org/api ./contrib/google.golang.org/api/internal/gen_endpoints + ./contrib/google.golang.org/genai ./contrib/google.golang.org/grpc ./contrib/gorilla/mux ./contrib/gorm.io/gorm.v1 diff --git a/go.work.sum b/go.work.sum index 20f199d5e82..1c7a572d550 100644 --- a/go.work.sum +++ b/go.work.sum @@ -21,6 +21,7 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q= cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI= cloud.google.com/go/accessapproval v1.8.8 h1:gq8OS+rQWgGRo91D2qztN+ion6AZ2T1CxBIu0ifCmVo= @@ -56,11 +57,13 @@ cloud.google.com/go/asset v1.22.1 h1:wimPPWu5gjBkPY1576vr+YxfoLKVhAK9zM2XrEpdKQ4 cloud.google.com/go/asset v1.22.1/go.mod h1:NlvWwmca7CX6BIBEdRNxOocH6DowmBghAAHucOHuHng= cloud.google.com/go/assuredworkloads v1.13.0 h1:NQXyyGLksPmiapE1Oc64a3cMwYIBAoDBg6cWR+B3eaY= cloud.google.com/go/assuredworkloads v1.13.0/go.mod h1:o/oHEOnUlribR+uJWTKQo8A5RhSl9K9FNeMOew4TJ3M= +cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= cloud.google.com/go/auth v0.16.4/go.mod h1:j10ncYwjX/g3cdX7GpEzsdM+d+ZNsXAbb6qXA7p1Y5M= cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ= cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ= cloud.google.com/go/auth v0.18.0/go.mod h1:wwkPM1AgE1f2u6dG443MiWoD8C3BtOywNsUMcUTVDRo= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/automl v1.15.0 h1:YRwLbsBv4yApX64pkrdyy4emhWE6lHEnljX4b1aTQC4= cloud.google.com/go/automl v1.15.0/go.mod h1:U9zOtQb8zVrFNGTuW3BfxeqmLyeleLgT9B12EaXfODg= cloud.google.com/go/baremetalsolution v1.4.0 h1:g67fjVdrNCHZl8jDWdZvo+6zGTTMMuvNWO7HSgG8lnI= @@ -219,6 +222,7 @@ cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXH cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA= cloud.google.com/go/logging v1.13.2 h1:qqlHCBvieJT9Cdq4QqYx1KPadCQ2noD4FK02eNqHAjA= cloud.google.com/go/logging v1.13.2/go.mod h1:zaybliM3yun1J8mU2dVQ1/qDzjbOqEijZCn6hSBtKak= +cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= cloud.google.com/go/longrunning v0.6.6/go.mod h1:hyeGJUrPHcx0u2Uu1UFSoYZLn4lkMrccJig0t4FI7yw= cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY= cloud.google.com/go/longrunning v0.7.0/go.mod h1:ySn2yXmjbK9Ba0zsQqunhDkYi0+9rlXIwnoAf+h+TPY= @@ -347,6 +351,7 @@ cloud.google.com/go/trace v1.11.5/go.mod h1:TwblCcqNInriu5/qzaeYEIH7wzUcchSdeY2l cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= +cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= cloud.google.com/go/translate v1.12.7 h1:aSxMbfJ3MVmEdQzu5jGXmPPxCAb1ySsor2yBMCI5MT4= cloud.google.com/go/translate v1.12.7/go.mod h1:wwJp14NZyWvcrFANhIXutXj0pOBkYciBHwSlUOykcjI= cloud.google.com/go/video v1.27.1 h1:Hp+2AeM7b3AagdHcyh2820UTzSbGyqpFJVMu0nHbBcw= @@ -1084,6 +1089,8 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh github.com/eapache/go-resiliency v1.4.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/eliben/go-sentencepiece v0.7.0 h1:QpP9HpLXF7/TAZoskolXm7heEWkh9vpHVUgGR1AbY3o= +github.com/eliben/go-sentencepiece v0.7.0/go.mod h1:nNYk4aMzgBoI6QFp4LUG8Eu1uO9fHD9L5ZEre93o9+c= github.com/emicklei/go-restful v2.16.0+incompatible h1:rgqiKNjTnFQA6kkhFe16D8epTksy9HQ1MyrbDXSdYhM= github.com/emicklei/go-restful v2.16.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= @@ -1168,7 +1175,6 @@ github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -1224,11 +1230,14 @@ github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/cloud-bigtable-clients-test v0.0.4 h1:9f+NjgCZHLx7t2lyL+Zhyg5f9/eFNI4RryGWlbcTwqk= github.com/googleapis/cloud-bigtable-clients-test v0.0.4/go.mod h1:NNHPqSxC2OBSLmt1j/qofCRRzL0OYZxk24CsicIe8MA= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.5/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= github.com/googleapis/gax-go/v2 v2.16.0/go.mod h1:o1vfQjjNZn4+dPnRdl/4ZD7S9414Y4xA+a/6Icj6l14= @@ -2031,10 +2040,12 @@ go.opentelemetry.io/contrib/detectors/gcp v1.38.0/go.mod h1:SU+iU7nu5ud4oCb3LQOh go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/detectors/gcp v1.42.0/go.mod h1:W9zQ439utxymRrXsUOzZbFX4JhLxXU4+ZnCt8GG7yA8= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= @@ -2044,6 +2055,7 @@ go.opentelemetry.io/contrib/otelconf v0.18.0/go.mod h1:FcP7k+JLwBLdOxS6qY6VQ/4b5 go.opentelemetry.io/contrib/otelconf v0.23.0 h1:s3C7KdMYiutf4rC8hKFA0WOIDG+gIru8ajjQKS59ir8= go.opentelemetry.io/contrib/otelconf v0.23.0/go.mod h1:0kN2tcccZS82e7IZlo045gkcL8/8dup1k25sf9ypGxM= go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= @@ -2063,14 +2075,10 @@ go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.18.0/go.mod h1:W2 go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0/go.mod h1:RolT8tWtfHcjajEH5wFIZ4Dgh5jpPdFXYV9pTAk/qjc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.42.0/go.mod h1:mBFWu/WOVDkWWsR7Tx7h6EpQB8wsv7P0Yrh0Pb7othc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= go.opentelemetry.io/otel/exporters/prometheus v0.57.0/go.mod h1:QpFWz1QxqevfjwzYdbMb4Y1NnlJvqSGwyuU0B4iuc9c= -go.opentelemetry.io/otel/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18BqlOuz2PWEvs8yM7Q6XE= go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.14.0 h1:B/g+qde6Mkzxbry5ZZag0l7QrQBCtVm7lVjaLgmpje8= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.14.0/go.mod h1:mOJK8eMmgW6ocDJn6Bn11CcZ05gi3P8GylBXEkZtbgA= @@ -2088,6 +2096,7 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41l go.opentelemetry.io/otel/log v0.14.0/go.mod h1:5jRG92fEAgx0SU/vFPxmJvhIuDU9E1SUnEQrMlJpOno= go.opentelemetry.io/otel/log/logtest v0.14.0/go.mod h1:IuguGt8XVP4XA4d2oEEDMVDBBCesMg8/tSGWDjuKfoA= go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= @@ -2117,6 +2126,7 @@ go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= @@ -2251,6 +2261,7 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= @@ -2300,6 +2311,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= @@ -2387,6 +2399,7 @@ golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= @@ -2640,9 +2653,11 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/genproto/googleapis/rpc v0.0.0-20240311132316-a219d84964c2/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= @@ -2714,6 +2729,7 @@ google.golang.org/grpc/security/advancedtls v1.0.0/go.mod h1:o+s4go+e1PJ2AjuQMY5 google.golang.org/grpc/stats/opencensus v1.0.0 h1:evSYcRZaSToQp+borzWE52+03joezZeXcKJvZDfkUJA= google.golang.org/grpc/stats/opencensus v1.0.0/go.mod h1:FhdkeYvN43wLYUnapVuRJJ9JXkNwe403iLUW2LKSnjs= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= diff --git a/instrumentation/packages.go b/instrumentation/packages.go index e2db0e5cb98..d57fe23fe49 100644 --- a/instrumentation/packages.go +++ b/instrumentation/packages.go @@ -79,6 +79,7 @@ const ( PackageUptraceBun Package = "uptrace/bun" PackageLogSlog Package = "log/slog" PackageModelContextProtocolGoSDK Package = "modelcontextprotocol/go-sdk" + PackageGoogleAPIsGoGenAI Package = "google.golang.org/genai" PackageValkeyIoValkeyGo Package = "valkey-io/valkey-go" PackageAzureAPIMCallout Package = "azure/apim-callout" @@ -919,6 +920,18 @@ var packages = map[Package]PackageInfo{ }, }, }, + PackageGoogleAPIsGoGenAI: { + TracedPackage: "google.golang.org/genai", + EnvVarPrefix: "GOOGLE_GENAI", + naming: map[Component]componentNames{ + ComponentDefault: { + useDDServiceV0: true, + buildServiceNameV0: staticName("google-genai"), + buildOpNameV0: staticName("google.genai.request"), + buildOpNameV1: staticName("google.genai.request"), + }, + }, + }, PackageEmickleiGoRestful: { TracedPackage: "github.com/emicklei/go-restful", EnvVarPrefix: "RESTFUL", diff --git a/internal/env/supported_configurations.gen.go b/internal/env/supported_configurations.gen.go index 58e7c28ca97..672815ae2eb 100644 --- a/internal/env/supported_configurations.gen.go +++ b/internal/env/supported_configurations.gen.go @@ -185,6 +185,7 @@ var SupportedConfigurations = map[string]struct{}{ "DD_TRACE_GOCQL_COMPAT": {}, "DD_TRACE_GOJI_ANALYTICS_ENABLED": {}, "DD_TRACE_GOOGLE_API_ANALYTICS_ENABLED": {}, + "DD_TRACE_GOOGLE_GENAI_ANALYTICS_ENABLED": {}, "DD_TRACE_GOPG_ANALYTICS_ENABLED": {}, "DD_TRACE_GQLGEN_ANALYTICS_ENABLED": {}, "DD_TRACE_GRAPHQL_ANALYTICS_ENABLED": {}, diff --git a/internal/env/supported_configurations.json b/internal/env/supported_configurations.json index be9045694d4..2595d0048d1 100644 --- a/internal/env/supported_configurations.json +++ b/internal/env/supported_configurations.json @@ -1241,6 +1241,13 @@ "default": "false" } ], + "DD_TRACE_GOOGLE_GENAI_ANALYTICS_ENABLED": [ + { + "implementation": "A", + "type": "boolean", + "default": "false" + } + ], "DD_TRACE_GOPG_ANALYTICS_ENABLED": [ { "implementation": "A", diff --git a/internal/stacktrace/contribs_generated.go b/internal/stacktrace/contribs_generated.go index ebd242ee677..12ddd46ebe3 100644 --- a/internal/stacktrace/contribs_generated.go +++ b/internal/stacktrace/contribs_generated.go @@ -302,6 +302,7 @@ func generatedThirdPartyLibraries() []string { "github.com/elastic/go-elasticsearch/v6", "github.com/elastic/go-elasticsearch/v7", "github.com/elastic/go-elasticsearch/v8", + "github.com/eliben/go-sentencepiece", "github.com/emicklei/go-restful/v3", "github.com/envoyproxy/go-control-plane", "github.com/envoyproxy/go-control-plane/envoy", @@ -767,6 +768,7 @@ func generatedThirdPartyLibraries() []string { "gonum.org/v1/gonum", "google.golang.org/api", "google.golang.org/appengine", + "google.golang.org/genai", "google.golang.org/genproto", "google.golang.org/genproto/googleapis/api", "google.golang.org/genproto/googleapis/bytestream",