Skip to content

Commit 8af2faa

Browse files
committed
manual instrumentation example
1 parent 07a13e0 commit 8af2faa

File tree

7 files changed

+232
-15
lines changed

7 files changed

+232
-15
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ run: ## Run the example application with environment variables (usage: make run
3131
echo "Usage: make run <example_name>"; \
3232
echo "Available examples:"; \
3333
echo " simple-chat"; \
34+
echo " manual-otel"; \
3435
exit 1; \
3536
fi
3637
@if [ -f .env ]; then \

examples/manual-otel/go.mod

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module manual-otel-example
2+
3+
go 1.25.1
4+
5+
require (
6+
github.com/JudgmentLabs/judgeval-go v0.0.0
7+
go.opentelemetry.io/otel v1.38.0
8+
go.opentelemetry.io/otel/sdk v1.38.0
9+
go.opentelemetry.io/otel/trace v1.38.0
10+
)
11+
12+
require (
13+
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
14+
github.com/go-logr/logr v1.4.3 // indirect
15+
github.com/go-logr/stdr v1.2.2 // indirect
16+
github.com/google/uuid v1.6.0 // indirect
17+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
18+
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
19+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
20+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
21+
go.opentelemetry.io/otel/metric v1.38.0 // indirect
22+
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
23+
golang.org/x/net v0.43.0 // indirect
24+
golang.org/x/sys v0.35.0 // indirect
25+
golang.org/x/text v0.28.0 // indirect
26+
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
27+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
28+
google.golang.org/grpc v1.75.0 // indirect
29+
google.golang.org/protobuf v1.36.8 // indirect
30+
)
31+
32+
replace github.com/JudgmentLabs/judgeval-go => ../../

examples/manual-otel/go.sum

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
2+
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
6+
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
7+
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
8+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
9+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
10+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
11+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
12+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
13+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
14+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
15+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
16+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
17+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
18+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
19+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
20+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
21+
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
22+
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
23+
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
24+
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
25+
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
26+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
27+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
28+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
29+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
30+
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
31+
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
32+
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
33+
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
34+
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
35+
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
36+
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
37+
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
38+
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
39+
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
40+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
41+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
42+
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
43+
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
44+
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
45+
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
46+
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
47+
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
48+
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
49+
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
50+
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
51+
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
52+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
53+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
54+
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
55+
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
56+
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
57+
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
58+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
59+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

examples/manual-otel/main.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"time"
8+
9+
"github.com/JudgmentLabs/judgeval-go/pkg/tracer"
10+
"go.opentelemetry.io/otel"
11+
"go.opentelemetry.io/otel/attribute"
12+
"go.opentelemetry.io/otel/sdk/resource"
13+
sdktrace "go.opentelemetry.io/otel/sdk/trace"
14+
)
15+
16+
func processData(ctx context.Context, data string) string {
17+
_, span := otel.Tracer("data-processor").Start(ctx, "process_data")
18+
defer span.End()
19+
20+
span.SetAttributes(
21+
attribute.String("data.input", data),
22+
attribute.Int("data.length", len(data)),
23+
)
24+
25+
time.Sleep(100 * time.Millisecond)
26+
27+
result := fmt.Sprintf("Processed: %s", data)
28+
span.SetAttributes(attribute.String("data.output", result))
29+
30+
return result
31+
}
32+
33+
func initOtel(judgmentTracer *tracer.Tracer) (func(), error) {
34+
res, err := resource.New(context.Background(),
35+
resource.WithAttributes(
36+
attribute.String("service.name", "manual-otel-example"),
37+
attribute.String("service.version", "1.0.0"),
38+
attribute.String("telemetry.sdk.name", "opentelemetry"),
39+
attribute.String("telemetry.sdk.version", "1.0.0"),
40+
),
41+
)
42+
if err != nil {
43+
return nil, fmt.Errorf("failed to create resource: %w", err)
44+
}
45+
46+
var spanExporter sdktrace.SpanExporter
47+
if judgmentTracer != nil {
48+
spanExporter = judgmentTracer.GetSpanExporter()
49+
}
50+
51+
tp := sdktrace.NewTracerProvider(
52+
sdktrace.WithResource(res),
53+
sdktrace.WithSpanProcessor(sdktrace.NewBatchSpanProcessor(spanExporter)),
54+
)
55+
56+
otel.SetTracerProvider(tp)
57+
58+
return func() {
59+
time.Sleep(10 * time.Second)
60+
if err := tp.Shutdown(context.Background()); err != nil {
61+
log.Printf("Error shutting down tracer provider: %v", err)
62+
}
63+
}, nil
64+
}
65+
66+
func main() {
67+
fmt.Println("Manual OpenTelemetry Instrumentation Example")
68+
fmt.Println("===========================================")
69+
70+
judgmentTracer, _ := tracer.NewTracer(
71+
tracer.WithConfiguration(tracer.NewTracerConfiguration(
72+
tracer.WithProjectName("manual-otel-example"),
73+
)),
74+
tracer.WithInitialize(false),
75+
)
76+
77+
cleanup, _ := initOtel(judgmentTracer)
78+
defer cleanup()
79+
defer judgmentTracer.Shutdown(context.Background())
80+
81+
ctx := context.Background()
82+
83+
ctx, rootSpan := otel.Tracer("main").Start(ctx, "manual_instrumentation_example")
84+
rootSpan.SetAttributes(attribute.String("example.type", "manual_otel"))
85+
86+
result1 := processData(ctx, "Hello, World!")
87+
fmt.Printf("Result 1: %s\n", result1)
88+
89+
result2 := processData(ctx, "Manual instrumentation")
90+
fmt.Printf("Result 2: %s\n", result2)
91+
92+
judgmentSpan, _ := judgmentTracer.Span(ctx, "judgment_metrics")
93+
judgmentTracer.SetGeneralSpan(judgmentSpan)
94+
judgmentTracer.SetAttribute(judgmentSpan, "service.type", "manual_otel")
95+
96+
requestData := map[string]interface{}{
97+
"endpoint": "/api/process",
98+
"method": "POST",
99+
"timestamp": time.Now().Unix(),
100+
}
101+
judgmentTracer.SetInput(judgmentSpan, requestData)
102+
103+
time.Sleep(50 * time.Millisecond)
104+
105+
responseData := map[string]interface{}{
106+
"status_code": 200,
107+
"response_time_ms": 50,
108+
"processed_items": 2,
109+
}
110+
judgmentTracer.SetOutput(judgmentSpan, responseData)
111+
judgmentSpan.End()
112+
113+
rootSpan.End()
114+
115+
fmt.Println("\nExample completed!")
116+
}

examples/simple-chat/main.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,9 @@ func main() {
155155

156156
if os.Getenv("JUDGMENT_API_URL") != "" && os.Getenv("JUDGMENT_API_KEY") != "" {
157157
t, err := tracer.NewTracer(
158-
tracer.WithConfiguration(tracer.TracerConfiguration{
159-
APIURL: os.Getenv("JUDGMENT_API_URL"),
160-
APIKey: os.Getenv("JUDGMENT_API_KEY"),
161-
OrganizationID: os.Getenv("JUDGMENT_ORG_ID"),
162-
ProjectName: "default_project",
163-
EnableEvaluation: true,
164-
}),
158+
tracer.WithConfiguration(tracer.NewTracerConfiguration(
159+
tracer.WithProjectName("default_project"),
160+
)),
165161
)
166162
if err != nil {
167163
fmt.Printf("Warning: Failed to initialize tracer: %v\n", err)

pkg/tracer/base_tracer.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,20 @@ func WithEnableEvaluation(enableEvaluation bool) TracerConfigurationOptions {
6060
}
6161
}
6262

63+
func NewTracerConfiguration(options ...TracerConfigurationOptions) TracerConfiguration {
64+
config := TracerConfiguration{
65+
APIURL: env.JudgmentAPIURL,
66+
APIKey: env.JudgmentAPIKey,
67+
OrganizationID: env.JudgmentOrgID,
68+
}
69+
70+
for _, option := range options {
71+
option(&config)
72+
}
73+
74+
return config
75+
}
76+
6377
type SerializerFunc func(obj interface{}) string
6478

6579
type baseTracer struct {

pkg/tracer/tracer.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66

7-
"github.com/JudgmentLabs/judgeval-go/pkg/env"
87
"github.com/JudgmentLabs/judgeval-go/pkg/internal/api"
98
"github.com/JudgmentLabs/judgeval-go/pkg/internal/api/models"
109
"github.com/JudgmentLabs/judgeval-go/pkg/logger"
@@ -52,19 +51,19 @@ func WithInitialize(initialize bool) TracerOptions {
5251

5352
func NewTracer(options ...TracerOptions) (*Tracer, error) {
5453
config := &TracerConfig{
55-
Configuration: TracerConfiguration{
56-
APIURL: env.JudgmentAPIURL,
57-
APIKey: env.JudgmentAPIKey,
58-
OrganizationID: env.JudgmentOrgID,
59-
},
60-
Serializer: DefaultJSONSerializer,
61-
Initialize: true,
54+
Configuration: NewTracerConfiguration(),
55+
Serializer: DefaultJSONSerializer,
56+
Initialize: true,
6257
}
6358

6459
for _, option := range options {
6560
option(config)
6661
}
6762

63+
return newTracerWithConfig(config)
64+
}
65+
66+
func newTracerWithConfig(config *TracerConfig) (*Tracer, error) {
6867
if config.Configuration.APIURL == "" {
6968
return nil, fmt.Errorf("configuration 'APIURL' is required")
7069
}

0 commit comments

Comments
 (0)