mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-07-09 17:28:58 +00:00
202 lines
5.2 KiB
Go
202 lines
5.2 KiB
Go
package telemetry
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
|
"go.opentelemetry.io/otel/sdk/resource"
|
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
)
|
|
|
|
func setupEnabledTelemetry(t *testing.T) {
|
|
t.Helper()
|
|
tp := sdktrace.NewTracerProvider(sdktrace.WithResource(resource.Default()))
|
|
mp := sdkmetric.NewMeterProvider(sdkmetric.WithResource(resource.Default()))
|
|
otel.SetTracerProvider(tp)
|
|
otel.SetMeterProvider(mp)
|
|
tracerProvider = tp
|
|
meterProvider = mp
|
|
initialized = true
|
|
shutdownFuncs = []func(context.Context) error{
|
|
func(ctx context.Context) error { return tp.Shutdown(ctx) },
|
|
func(ctx context.Context) error { return mp.Shutdown(ctx) },
|
|
}
|
|
initMetricsOnce = false
|
|
t.Cleanup(func() {
|
|
_ = tp.Shutdown(context.Background())
|
|
_ = mp.Shutdown(context.Background())
|
|
tracerProvider = nil
|
|
meterProvider = nil
|
|
initialized = false
|
|
shutdownFuncs = nil
|
|
initMetricsOnce = false
|
|
})
|
|
}
|
|
|
|
func captureStderr(t *testing.T, fn func()) string {
|
|
t.Helper()
|
|
r, w, err := os.Pipe()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
oldStderr := os.Stderr
|
|
os.Stderr = w
|
|
defer func() { os.Stderr = oldStderr }()
|
|
|
|
fn()
|
|
_ = w.Close()
|
|
|
|
var buf bytes.Buffer
|
|
_, _ = io.Copy(&buf, r)
|
|
return buf.String()
|
|
}
|
|
|
|
func TestEvent_Enabled(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
ctx := context.Background()
|
|
Event(ctx, "test.event", attribute.String("key", "value"))
|
|
}
|
|
|
|
func TestEvent_Disabled(t *testing.T) {
|
|
initialized = false
|
|
shutdownFuncs = nil
|
|
defer func() { initialized = false }()
|
|
Event(context.Background(), "test.event")
|
|
}
|
|
|
|
func TestEvent_NilCtx(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
Event(nil, "test.event") //nolint:staticcheck
|
|
}
|
|
|
|
func TestEventf_Enabled(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
ctx := context.Background()
|
|
Eventf(ctx, "test.eventf", "hello world", attribute.Int("count", 5))
|
|
}
|
|
|
|
func TestErrorEvent_Enabled(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
ctx := context.Background()
|
|
ErrorEvent(ctx, "test.error", errors.New("something failed"), attribute.String("detail", "extra"))
|
|
}
|
|
|
|
func TestErrorEvent_NilErr(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
ctx := context.Background()
|
|
ErrorEvent(ctx, "test.error", nil)
|
|
}
|
|
|
|
func TestErrorEvent_NilCtx(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
ErrorEvent(nil, "test.error", errors.New("fail")) //nolint:staticcheck
|
|
}
|
|
|
|
func TestErrorEvent_Disabled(t *testing.T) {
|
|
initialized = false
|
|
shutdownFuncs = nil
|
|
defer func() { initialized = false }()
|
|
ErrorEvent(context.Background(), "test.error", errors.New("fail"))
|
|
}
|
|
|
|
func TestPhaseEvent_Success(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
ctx := context.Background()
|
|
PhaseEvent(ctx, "scan", "main.go", 500*time.Millisecond, nil)
|
|
}
|
|
|
|
func TestPhaseEvent_WithError(t *testing.T) {
|
|
setupEnabledTelemetry(t)
|
|
ctx := context.Background()
|
|
PhaseEvent(ctx, "scan", "main.go", 500*time.Millisecond, errors.New("parse error"))
|
|
}
|
|
|
|
func TestPrintTraceSummary_WithTokenDetails(t *testing.T) {
|
|
PrintTraceSummary(5, 10, 1000, 200, 1200, 0, 0, 3*time.Second)
|
|
}
|
|
|
|
func TestPrintTraceSummary_WithCacheTokens(t *testing.T) {
|
|
PrintTraceSummary(3, 2, 500, 100, 600, 200, 50, 2*time.Second)
|
|
}
|
|
|
|
func TestPrintTraceSummary_NoTokenDetails(t *testing.T) {
|
|
PrintTraceSummary(2, 1, 0, 0, 500, 0, 0, 1*time.Second)
|
|
}
|
|
|
|
func TestPrintToolCallStarted_WithArgs(t *testing.T) {
|
|
PrintToolCallStarted("file_read", map[string]any{"path": "main.go"})
|
|
}
|
|
|
|
func TestPrintToolCallStarted_NoArgs(t *testing.T) {
|
|
PrintToolCallStarted("list_files", nil)
|
|
}
|
|
|
|
func TestPrintToolCallFinished(t *testing.T) {
|
|
PrintToolCallFinished("file_read", 123*time.Millisecond)
|
|
}
|
|
|
|
func TestPrintToolCallError(t *testing.T) {
|
|
out := captureStderr(t, func() {
|
|
PrintToolCallError("file_read", fmt.Errorf("permission denied"))
|
|
})
|
|
if !strings.Contains(out, "✘ file_read") {
|
|
t.Errorf("expected tool name with X mark, got %q", out)
|
|
}
|
|
if !strings.Contains(out, "permission denied") {
|
|
t.Errorf("expected error message, got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestFormatDuration(t *testing.T) {
|
|
tests := []struct {
|
|
dur time.Duration
|
|
want string
|
|
}{
|
|
{0, "0s"},
|
|
{1500 * time.Millisecond, "1.5s"},
|
|
{60 * time.Second, "1m0s"},
|
|
{123 * time.Millisecond, "123ms"},
|
|
{2*time.Minute + 30*time.Second, "2m30s"},
|
|
}
|
|
for _, tc := range tests {
|
|
got := FormatDuration(tc.dur)
|
|
if got != tc.want {
|
|
t.Errorf("FormatDuration(%v) = %q, want %q", tc.dur, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSummarizeArgs(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args map[string]any
|
|
want string
|
|
}{
|
|
{"nil map", nil, ""},
|
|
{"empty map", map[string]any{}, ""},
|
|
{"path key returns quoted", map[string]any{"path": "foo/bar.go"}, `"foo/bar.go"`},
|
|
{"search key returns quoted", map[string]any{"search": "hello"}, `"hello"`},
|
|
{"query key returns quoted", map[string]any{"query": "world"}, `"world"`},
|
|
{"pattern key returns quoted", map[string]any{"pattern": "*.go"}, `"*.go"`},
|
|
{"generic short value", map[string]any{"foo": "bar"}, "foo=bar"},
|
|
{"long value skipped", map[string]any{"data": string(make([]byte, 60))}, ""},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := summarizeArgs(tc.args)
|
|
if got != tc.want {
|
|
t.Errorf("summarizeArgs(%v) = %q, want %q", tc.args, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|