@@ -2,6 +2,7 @@ package tracing
22
33import (
44 "context"
5+ "encoding/json"
56 "errors"
67 "net/http"
78 "net/http/httptest"
@@ -15,17 +16,26 @@ import (
1516
1617func TestTracing_UnmarshalCaddyfile (t * testing.T ) {
1718 tests := []struct {
18- name string
19- spanName string
20- d * caddyfile.Dispenser
21- wantErr bool
19+ name string
20+ spanName string
21+ spanAttributes map [string ]string
22+ d * caddyfile.Dispenser
23+ wantErr bool
2224 }{
2325 {
2426 name : "Full config" ,
2527 spanName : "my-span" ,
28+ spanAttributes : map [string ]string {
29+ "attr1" : "value1" ,
30+ "attr2" : "value2" ,
31+ },
2632 d : caddyfile .NewTestDispenser (`
2733tracing {
2834 span my-span
35+ span_attributes {
36+ attr1 value1
37+ attr2 value2
38+ }
2939}` ),
3040 wantErr : false ,
3141 },
@@ -42,6 +52,21 @@ tracing {
4252 name : "Empty config" ,
4353 d : caddyfile .NewTestDispenser (`
4454tracing {
55+ }` ),
56+ wantErr : false ,
57+ },
58+ {
59+ name : "Only span attributes" ,
60+ spanAttributes : map [string ]string {
61+ "service.name" : "my-service" ,
62+ "service.version" : "1.0.0" ,
63+ },
64+ d : caddyfile .NewTestDispenser (`
65+ tracing {
66+ span_attributes {
67+ service.name my-service
68+ service.version 1.0.0
69+ }
4570}` ),
4671 wantErr : false ,
4772 },
@@ -56,6 +81,20 @@ tracing {
5681 if ot .SpanName != tt .spanName {
5782 t .Errorf ("UnmarshalCaddyfile() SpanName = %v, want SpanName %v" , ot .SpanName , tt .spanName )
5883 }
84+
85+ if len (tt .spanAttributes ) > 0 {
86+ if ot .SpanAttributes == nil {
87+ t .Errorf ("UnmarshalCaddyfile() SpanAttributes is nil, expected %v" , tt .spanAttributes )
88+ } else {
89+ for key , expectedValue := range tt .spanAttributes {
90+ if actualValue , exists := ot .SpanAttributes [key ]; ! exists {
91+ t .Errorf ("UnmarshalCaddyfile() SpanAttributes missing key %v" , key )
92+ } else if actualValue != expectedValue {
93+ t .Errorf ("UnmarshalCaddyfile() SpanAttributes[%v] = %v, want %v" , key , actualValue , expectedValue )
94+ }
95+ }
96+ }
97+ }
5998 })
6099 }
61100}
@@ -79,6 +118,26 @@ func TestTracing_UnmarshalCaddyfile_Error(t *testing.T) {
79118 d : caddyfile .NewTestDispenser (`
80119tracing {
81120 span
121+ }` ),
122+ wantErr : true ,
123+ },
124+ {
125+ name : "Span attributes missing value" ,
126+ d : caddyfile .NewTestDispenser (`
127+ tracing {
128+ span_attributes {
129+ key
130+ }
131+ }` ),
132+ wantErr : true ,
133+ },
134+ {
135+ name : "Span attributes too many arguments" ,
136+ d : caddyfile .NewTestDispenser (`
137+ tracing {
138+ span_attributes {
139+ key value extra
140+ }
82141}` ),
83142 wantErr : true ,
84143 },
@@ -181,6 +240,100 @@ func TestTracing_ServeHTTP_Next_Error(t *testing.T) {
181240 }
182241}
183242
243+ func TestTracing_ServeHTTP_With_SpanAttributes (t * testing.T ) {
244+ ot := & Tracing {
245+ SpanName : "mySpan" ,
246+ SpanAttributes : map [string ]string {
247+ "service.name" : "test-service" ,
248+ "service.version" : "1.0.0" ,
249+ "custom.attr" : "test-value" ,
250+ },
251+ }
252+
253+ req := createRequestWithContext ("GET" , "https://example.com/foo" )
254+ w := httptest .NewRecorder ()
255+
256+ var handler caddyhttp.HandlerFunc = func (writer http.ResponseWriter , request * http.Request ) error {
257+ traceparent := request .Header .Get ("Traceparent" )
258+ if traceparent == "" || strings .HasPrefix (traceparent , "00-00000000000000000000000000000000-0000000000000000" ) {
259+ t .Errorf ("Invalid traceparent: %v" , traceparent )
260+ }
261+
262+ return nil
263+ }
264+
265+ ctx , cancel := caddy .NewContext (caddy.Context {Context : context .Background ()})
266+ defer cancel ()
267+
268+ if err := ot .Provision (ctx ); err != nil {
269+ t .Errorf ("Provision error: %v" , err )
270+ t .FailNow ()
271+ }
272+
273+ if err := ot .ServeHTTP (w , req , handler ); err != nil {
274+ t .Errorf ("ServeHTTP error: %v" , err )
275+ }
276+
277+ // Verify span attributes were configured
278+ if ot .otel .spanAttributes == nil {
279+ t .Error ("Expected span attributes to be set on otel wrapper" )
280+ }
281+
282+ expectedAttrs := map [string ]string {
283+ "service.name" : "test-service" ,
284+ "service.version" : "1.0.0" ,
285+ "custom.attr" : "test-value" ,
286+ }
287+
288+ for key , expectedValue := range expectedAttrs {
289+ if actualValue , exists := ot .otel .spanAttributes [key ]; ! exists {
290+ t .Errorf ("Expected span attribute %s to exist" , key )
291+ } else if actualValue != expectedValue {
292+ t .Errorf ("Expected span attribute %s = %s, got %s" , key , expectedValue , actualValue )
293+ }
294+ }
295+ }
296+
297+ func TestTracing_JSON_Configuration (t * testing.T ) {
298+ // Test that our struct correctly marshals to and from JSON
299+ original := & Tracing {
300+ SpanName : "test-span" ,
301+ SpanAttributes : map [string ]string {
302+ "service.name" : "test-service" ,
303+ "service.version" : "1.0.0" ,
304+ "env" : "test" ,
305+ },
306+ }
307+
308+ jsonData , err := json .Marshal (original )
309+ if err != nil {
310+ t .Fatalf ("Failed to marshal to JSON: %v" , err )
311+ }
312+
313+ var unmarshaled Tracing
314+ if err := json .Unmarshal (jsonData , & unmarshaled ); err != nil {
315+ t .Fatalf ("Failed to unmarshal from JSON: %v" , err )
316+ }
317+
318+ if unmarshaled .SpanName != original .SpanName {
319+ t .Errorf ("Expected SpanName %s, got %s" , original .SpanName , unmarshaled .SpanName )
320+ }
321+
322+ if len (unmarshaled .SpanAttributes ) != len (original .SpanAttributes ) {
323+ t .Errorf ("Expected %d span attributes, got %d" , len (original .SpanAttributes ), len (unmarshaled .SpanAttributes ))
324+ }
325+
326+ for key , expectedValue := range original .SpanAttributes {
327+ if actualValue , exists := unmarshaled .SpanAttributes [key ]; ! exists {
328+ t .Errorf ("Expected span attribute %s to exist" , key )
329+ } else if actualValue != expectedValue {
330+ t .Errorf ("Expected span attribute %s = %s, got %s" , key , expectedValue , actualValue )
331+ }
332+ }
333+
334+ t .Logf ("JSON representation: %s" , string (jsonData ))
335+ }
336+
184337func createRequestWithContext (method string , url string ) * http.Request {
185338 r , _ := http .NewRequest (method , url , nil )
186339 repl := caddy .NewReplacer ()
0 commit comments