blob: cefa24acc2f3588b99624f979497f80f00b5d9ff [file] [log] [blame] [edit]
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package otel
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"sync"
"testing"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/core"
"golang.org/x/tools/internal/event/export"
"golang.org/x/tools/internal/event/label"
)
func TestConvertSpan(t *testing.T) {
span := &export.Span{
Name: "test-operation",
ID: export.SpanContext{
TraceID: export.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
SpanID: export.SpanID{1, 2, 3, 4, 5, 6, 7, 8},
},
ParentID: export.SpanID{8, 7, 6, 5, 4, 3, 2, 1},
}
result := convertSpan(span)
if result.Name != "test-operation" {
t.Errorf("expected name 'test-operation', got %q", result.Name)
}
if result.TraceID != "0102030405060708090a0b0c0d0e0f10" {
t.Errorf("unexpected traceId: %s", result.TraceID)
}
if result.SpanID != "0102030405060708" {
t.Errorf("unexpected spanId: %s", result.SpanID)
}
if result.ParentSpanID != "0807060504030201" {
t.Errorf("unexpected parentSpanId: %s", result.ParentSpanID)
}
if result.Kind != 1 {
t.Errorf("expected kind 1, got %d", result.Kind)
}
if result.Status.Code != 0 {
t.Errorf("expected status code 0, got %d", result.Status.Code)
}
}
// TestE2E_SpanExport is a minimal end-to-end test verifying the full pipeline.
func TestE2E_SpanExport(t *testing.T) {
var received []byte
var mu sync.Mutex
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
mu.Lock()
received, _ = io.ReadAll(r.Body)
mu.Unlock()
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
baseExporter := func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
return ctx
}
spansExporter := export.Spans(baseExporter)
otelExporter := NewExporter(context.Background(), WithEndpoint(server.URL))
chainedExporter := func(ctx context.Context, ev core.Event, lm label.Map) context.Context {
ctx = spansExporter(ctx, ev, lm)
return otelExporter.ProcessEvent(ctx, ev, lm)
}
event.SetExporter(chainedExporter)
ctx := context.Background()
ctx, end := event.Start(ctx, "e2e-span")
end()
otelExporter.Flush()
mu.Lock()
data := received
mu.Unlock()
if len(data) == 0 {
t.Fatal("no data received")
}
// Just verify it's valid JSON with a span
var req otlpTraceExportRequest
if err := json.Unmarshal(data, &req); err != nil {
t.Fatalf("invalid JSON: %v", err)
}
if len(req.ResourceSpans) == 0 ||
len(req.ResourceSpans[0].ScopeSpans) == 0 ||
len(req.ResourceSpans[0].ScopeSpans[0].Spans) == 0 {
t.Fatal("expected at least one span")
}
}