package mypackage_test
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/trulayer/client-go/trulayer"
)
func TestLLMPipelineEmitsSpans(t *testing.T) {
// 1. Set up a test server that captures every ingest POST.
var mu sync.Mutex
var bodies []map[string]interface{}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/v1/ingest/batch" {
b, _ := io.ReadAll(r.Body)
var payload map[string]interface{}
_ = json.Unmarshal(b, &payload)
mu.Lock()
bodies = append(bodies, payload)
mu.Unlock()
w.WriteHeader(201)
_, _ = w.Write([]byte(`{"ingested":1,"ids":["x"]}`))
} else {
w.WriteHeader(404)
}
}))
t.Cleanup(srv.Close)
// 2. Wire the client to the test server.
c := trulayer.NewClient("tl_test",
trulayer.WithBaseURL(srv.URL),
trulayer.WithFlushInterval(50*time.Millisecond),
)
t.Cleanup(func() { _ = c.Shutdown(context.Background()) })
// 3. Run your instrumented code.
ctx := context.Background()
trace, ctx := c.NewTrace(ctx, "answer-question")
trace.SetInput("What is the capital of France?")
span, ctx := trace.NewSpan(ctx, "llm-call", trulayer.SpanTypeLLM,
trulayer.WithSpanModel("gpt-4o-mini"),
)
span.SetOutput("Paris.")
span.SetTokens(12, 4)
span.End(ctx)
trace.SetOutput("Paris.")
trace.End(ctx)
// 4. Flush synchronously so the test server has received everything.
require.NoError(t, c.Flush(ctx))
// 5. Assert on the captured payload.
mu.Lock()
defer mu.Unlock()
require.NotEmpty(t, bodies, "expected at least one ingest call")
traces := bodies[0]["traces"].([]interface{})
require.Len(t, traces, 1)
got := traces[0].(map[string]interface{})
assert.Equal(t, "answer-question", got["name"])
spans := got["spans"].([]interface{})
require.Len(t, spans, 1)
s := spans[0].(map[string]interface{})
assert.Equal(t, "llm", s["type"])
assert.Equal(t, "gpt-4o-mini", s["model"])
}