@@ -271,6 +271,7 @@ func main() {
271271 routerAPI := flag .String ("router_api" , env ("TARGET_ROUTER_API_URL" , "http://localhost:8080" ), "Router API base URL" )
272272 routerMetrics := flag .String ("router_metrics" , env ("TARGET_ROUTER_METRICS_URL" , "http://localhost:9190/metrics" ), "Router metrics URL" )
273273 openwebuiURL := flag .String ("openwebui" , env ("TARGET_OPENWEBUI_URL" , "" ), "Open WebUI base URL" )
274+ jaegerURL := flag .String ("jaeger" , env ("TARGET_JAEGER_URL" , "" ), "Jaeger base URL" )
274275
275276 flag .Parse ()
276277
@@ -340,13 +341,27 @@ func main() {
340341 log .Printf ("Warning: Grafana URL not configured" )
341342 }
342343
343- // Smart /api/ router: route to Router API or Grafana API based on path
344+ // Jaeger API proxy (needs to be set up early for the smart router below)
345+ var jaegerAPIProxy * httputil.ReverseProxy
346+ if * jaegerURL != "" {
347+ // Create proxy for Jaeger API (no prefix stripping for /api/*)
348+ jaegerAPIProxy , _ = newReverseProxy (* jaegerURL , "" , false )
349+ }
350+
351+ // Smart /api/ router: route to Router API, Jaeger API, or Grafana API based on path
344352 mux .HandleFunc ("/api/" , func (w http.ResponseWriter , r * http.Request ) {
345353 // If path starts with /api/router/, use Router API proxy
346354 if strings .HasPrefix (r .URL .Path , "/api/router/" ) && routerAPIProxy != nil {
347355 routerAPIProxy .ServeHTTP (w , r )
348356 return
349357 }
358+ // If path is Jaeger API (services, traces, operations, etc.), use Jaeger proxy
359+ if jaegerAPIProxy != nil && (strings .HasPrefix (r .URL .Path , "/api/services" ) ||
360+ strings .HasPrefix (r .URL .Path , "/api/traces" ) ||
361+ strings .HasPrefix (r .URL .Path , "/api/operations" )) {
362+ jaegerAPIProxy .ServeHTTP (w , r )
363+ return
364+ }
350365 // Otherwise, if Grafana is configured, proxy to Grafana API
351366 if grafanaStaticProxy != nil {
352367 grafanaStaticProxy .ServeHTTP (w , r )
@@ -382,6 +397,31 @@ func main() {
382397 log .Printf ("Warning: Prometheus URL not configured" )
383398 }
384399
400+ // Jaeger proxy (optional) - expose full UI under /embedded/jaeger and its static assets under /static/
401+ if * jaegerURL != "" {
402+ jp , err := newReverseProxy (* jaegerURL , "/embedded/jaeger" , false )
403+ if err != nil {
404+ log .Fatalf ("jaeger proxy error: %v" , err )
405+ }
406+ // Jaeger UI (root UI under /embedded/jaeger)
407+ mux .Handle ("/embedded/jaeger" , jp )
408+ mux .Handle ("/embedded/jaeger/" , jp )
409+
410+ // Jaeger static assets are typically served under /static/* from the same origin
411+ // Provide a passthrough proxy without prefix stripping
412+ jStatic , _ := newReverseProxy (* jaegerURL , "" , false )
413+ mux .Handle ("/static/" , jStatic )
414+
415+ log .Printf ("Jaeger proxy configured: %s; static assets proxied at /static/" , * jaegerURL )
416+ } else {
417+ mux .HandleFunc ("/embedded/jaeger/" , func (w http.ResponseWriter , r * http.Request ) {
418+ w .Header ().Set ("Content-Type" , "application/json" )
419+ w .WriteHeader (http .StatusServiceUnavailable )
420+ w .Write ([]byte (`{"error":"Jaeger not configured","message":"TARGET_JAEGER_URL environment variable is not set"}` ))
421+ })
422+ log .Printf ("Info: Jaeger URL not configured (optional)" )
423+ }
424+
385425 // Open WebUI proxy (optional)
386426 if * openwebuiURL != "" {
387427 op , err := newReverseProxy (* openwebuiURL , "/embedded/openwebui" , true )
@@ -409,6 +449,9 @@ func main() {
409449 if * promURL != "" {
410450 log .Printf ("Prometheus: %s → /embedded/prometheus/" , * promURL )
411451 }
452+ if * jaegerURL != "" {
453+ log .Printf ("Jaeger: %s → /embedded/jaeger/" , * jaegerURL )
454+ }
412455 if * openwebuiURL != "" {
413456 log .Printf ("OpenWebUI: %s → /embedded/openwebui/" , * openwebuiURL )
414457 }
0 commit comments