knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/observability/tracing/provider_test.go (about) 1 /* 2 Copyright 2025 The Knative Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package tracing 18 19 import ( 20 "context" 21 "errors" 22 "testing" 23 24 "github.com/google/go-cmp/cmp" 25 "knative.dev/pkg/ptr" 26 ) 27 28 func TestNewTrackerProviderProtocols(t *testing.T) { 29 cases := []struct { 30 name string 31 c Config 32 wantErr bool 33 }{{ 34 name: "grpc", 35 c: Config{Protocol: ProtocolGRPC}, 36 }, { 37 name: "none", 38 c: Config{Protocol: ProtocolNone}, 39 }, { 40 name: "http", 41 c: Config{Protocol: ProtocolHTTPProtobuf}, 42 }, { 43 name: "bad protocol", 44 c: Config{Protocol: "bad"}, 45 wantErr: true, 46 }, { 47 name: "http - bad URL", 48 c: Config{ 49 Protocol: ProtocolHTTPProtobuf, 50 Endpoint: "://hello", 51 }, 52 wantErr: true, 53 }, { 54 name: "http with path in endpoint", 55 c: Config{ 56 Protocol: ProtocolHTTPProtobuf, 57 Endpoint: "http://example.com:9090/api/v1/otlp/v1/traces", 58 }, 59 }} 60 61 for _, tc := range cases { 62 t.Run(tc.name, func(t *testing.T) { 63 ctx := context.Background() 64 _, err := NewTracerProvider(ctx, tc.c) 65 66 if !tc.wantErr && err != nil { 67 t.Error("unexpected failed", err) 68 } else if tc.wantErr && err == nil { 69 t.Error("expected failure") 70 } 71 }) 72 } 73 } 74 75 func TestEndpointFor(t *testing.T) { 76 cases := []string{ 77 "OTEL_EXPORTER_OTLP_ENDPOINT", 78 "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", 79 } 80 81 optFunc := func(string) *string { 82 panic("unexpected call") 83 } 84 85 for _, envKey := range cases { 86 t.Run("override "+envKey, func(t *testing.T) { 87 t.Setenv(envKey, "https://override.example.com") 88 89 opt, err := endpointFor(Config{Endpoint: "https://otel.example.com"}, optFunc) 90 if err != nil { 91 t.Fatal("unexpected error", err) 92 } 93 94 if opt != nil { 95 t.Error("expected the option to not be present when 'OTEL_EXPORTER_OTLP_ENDPOINT' is set") 96 } 97 }) 98 } 99 100 t.Run("normal", func(t *testing.T) { 101 optFunc := func(string) *string { 102 result := "result" 103 return &result 104 } 105 opt, err := endpointFor(Config{Endpoint: "https://otel.example.com"}, optFunc) 106 if err != nil { 107 t.Fatal("unexpected error", err) 108 } 109 if *opt != "result" { 110 t.Error("expected option to work when no env vars are present") 111 } 112 }) 113 114 t.Run("missing scheme - defaults to https", func(t *testing.T) { 115 optFunc := func(r string) *string { 116 return &r 117 } 118 got, err := endpointFor(Config{Endpoint: "otel.example.com:8080"}, optFunc) 119 if err != nil { 120 t.Fatal("unexpected err", err) 121 } 122 123 want := ptr.String("https://otel.example.com:8080") 124 if diff := cmp.Diff(want, got); diff != "" { 125 t.Error("expected option to work when no env vars are present: (-want +got): ", diff) 126 } 127 }) 128 } 129 130 func TestTracerProviderShutdown(t *testing.T) { 131 want := errors.New("some error") 132 invoked := false 133 shutdown := func(context.Context) error { 134 invoked = true 135 return want 136 } 137 138 p := TracerProvider{shutdown: shutdown} 139 got := p.Shutdown(context.Background()) 140 141 if !invoked { 142 t.Fatal("expected shutdown to be invoked") 143 } 144 145 if !errors.Is(got, want) { 146 t.Error("unexpected error (-want +got): ", cmp.Diff(want, got)) 147 } 148 } 149 150 func TestSampleFor(t *testing.T) { 151 cfg := Config{ 152 SamplingRate: 0.85, 153 } 154 155 cases := []struct { 156 name string 157 env map[string]string 158 wantNilSampler bool 159 wantErr bool 160 }{{ 161 name: "sampler override", 162 env: map[string]string{ 163 "OTEL_TRACES_SAMPLER": "some-sampler", 164 }, 165 wantNilSampler: true, 166 }, { 167 name: "standard sampler", 168 wantNilSampler: false, 169 }, { 170 name: "sample arg override", 171 wantNilSampler: false, 172 env: map[string]string{ 173 "OTEL_TRACES_SAMPLER_ARG": "1.0", 174 }, 175 }, { 176 name: "sample arg override - bad input", 177 wantNilSampler: true, 178 wantErr: true, 179 env: map[string]string{ 180 "OTEL_TRACES_SAMPLER_ARG": "bad-ratio", 181 }, 182 }} 183 184 for _, tc := range cases { 185 t.Run(tc.name, func(t *testing.T) { 186 for k, v := range tc.env { 187 t.Setenv(k, v) 188 } 189 190 got, err := sampleFor(cfg) 191 if tc.wantNilSampler && got != nil { 192 t.Error("expected a nil sampler") 193 } else if !tc.wantNilSampler && got == nil { 194 t.Error("expected a non-nil sampler") 195 } 196 197 if tc.wantErr && err == nil { 198 t.Error("expected an error") 199 } else if !tc.wantErr && err != nil { 200 t.Error("unexpected error") 201 } 202 }) 203 } 204 }